diff --git a/.editorconfig b/.editorconfig index 4cead120d..57d0ce66a 100755 --- a/.editorconfig +++ b/.editorconfig @@ -12,7 +12,7 @@ indent_style = space tab_width = 4 # New line preferences -end_of_line = crlf +# end_of_line = crlf insert_final_newline = false #### .NET Coding Conventions #### @@ -58,7 +58,7 @@ dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error dotnet_style_readonly_field = true:error # Parameter preferences -dotnet_code_quality_unused_parameters = all:error +dotnet_code_quality_unused_parameters = all:warning #### C# Coding Conventions #### @@ -68,14 +68,14 @@ csharp_style_var_for_built_in_types = true:error csharp_style_var_when_type_is_apparent = true:error # Expression-bodied members -csharp_style_expression_bodied_accessors = true:error -csharp_style_expression_bodied_constructors = true:error -csharp_style_expression_bodied_indexers = true:error -csharp_style_expression_bodied_lambdas = true:error -csharp_style_expression_bodied_local_functions = true:error -csharp_style_expression_bodied_methods = true:error -csharp_style_expression_bodied_operators = true:error -csharp_style_expression_bodied_properties = true:error +csharp_style_expression_bodied_accessors =true:warning +csharp_style_expression_bodied_constructors =true:warning +csharp_style_expression_bodied_indexers =true:warning +csharp_style_expression_bodied_lambdas =true:warning +csharp_style_expression_bodied_local_functions =true:warning +csharp_style_expression_bodied_methods =true:warning +csharp_style_expression_bodied_operators =true:warning +csharp_style_expression_bodied_properties =true:warning # Pattern matching preferences csharp_style_pattern_matching_over_as_with_null_check = true:error @@ -101,7 +101,7 @@ csharp_style_pattern_local_over_anonymous_function = true:error csharp_style_prefer_index_operator = true:warning csharp_style_prefer_range_operator = true:warning csharp_style_throw_expression = true:error -csharp_style_unused_value_assignment_preference = discard_variable:error +csharp_style_unused_value_assignment_preference =discard_variable:warning csharp_style_unused_value_expression_statement_preference = discard_variable:error # 'using' directive preferences diff --git a/.gitattributes b/.gitattributes index 1ff0c4230..b72c2c601 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,7 @@ ############################################################################### # Set default behavior to automatically normalize line endings. ############################################################################### -* text=auto +* text eol=lf ############################################################################### # Set default behavior for command prompt diff. diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 04a9e8ef8..74c171c6f 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -10,24 +10,21 @@ jobs: - name: Check out repository uses: actions/checkout@v2 - name: Setup .NET Core - uses: actions/setup-dotnet@v1.7.2 + uses: actions/setup-dotnet@v1 with: - dotnet-version: '5.0.x' + dotnet-version: '6.0.x' + include-prerelease: true - name: Test source generator - run: dotnet test ./NetFabric.Hyperlinq.SourceGenerator.UnitTests/NetFabric.Hyperlinq.SourceGenerator.UnitTests.csproj + run: dotnet test ./NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj - name: Build solution run: dotnet build - name: Tests and coverage - run: dotnet test ./NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj -f:net5.0 -c:Release --collect:"XPlat Code Coverage" --settings coverlet.runsettings - - name: Get path to lcov file - id: get_lcov_path - shell: bash - run: printf '::set-output name=lcov_path::%s\n' ./NetFabric.Hyperlinq.UnitTests/TestResults/*/coverage.info + run: dotnet test ./NetFabric.Hyperlinq.Core.UnitTests/NetFabric.Hyperlinq.Core.UnitTests.csproj -f:net6.0 -p:CollectCoverage=true -p:CoverletOutputFormat=lcov -p:CoverletOutput=TestResults/ - name: Publish coverage report to coveralls.io uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ${{ steps.get_lcov_path.outputs.lcov_path }} + path-to-lcov: ./NetFabric.Hyperlinq.Core.UnitTests/TestResults/coverage.net6.0.info diff --git a/Benchmarks/AggressiveInliningBenchmarks.md b/Benchmarks/AggressiveInliningBenchmarks.md new file mode 100644 index 000000000..c9c638a13 --- /dev/null +++ b/Benchmarks/AggressiveInliningBenchmarks.md @@ -0,0 +1,29 @@ +## AggressiveInliningBenchmarks + +### Source +[AggressiveInliningBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/AggressiveInliningBenchmarks.cs) + +### References: +- Linq: 6.0.0-preview.5.21301.5 +- System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) +- System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) +- System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) + +### Results: +``` ini + +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) +Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + +Runtime=.NET 6.0 + +``` +| Method | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------- |------ |---------:|--------:|--------:|------:|------:|------:|------:|----------:| +| Baseline | 1000 | 545.7 ns | 1.04 ns | 0.97 ns | 1.00 | - | - | - | - | +| AggressiveInlining | 1000 | 544.8 ns | 1.32 ns | 1.24 ns | 1.00 | - | - | - | - | diff --git a/Benchmarks/AllBenchmarks.md b/Benchmarks/AllBenchmarks.md index 6c57d8713..e8de02988 100644 --- a/Benchmarks/AllBenchmarks.md +++ b/Benchmarks/AllBenchmarks.md @@ -4,52 +4,50 @@ [AllBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/AllBenchmarks.cs) ### References: -- Linq: 5.0.0-preview.7.20364.11 -- System.Linq.Async: [4.1.1](https://www.nuget.org/packages/System.Linq.Async/4.1.1) -- System.Interactive: [4.1.1](https://www.nuget.org/packages/System.Interactive/4.1.1) -- System.Interactive.Async: [4.1.1](https://www.nuget.org/packages/System.Interactive.Async/4.1.1) -- StructLinq: [0.19.2](https://www.nuget.org/packages/StructLinq/0.19.2) -- NetFabric.Hyperlinq: [3.0.0-beta26](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta26) +- Linq: 6.0.0-preview.5.21301.5 +- System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) +- System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) +- System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores -.NET Core SDK=5.0.100-preview.7.20366.6 - [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.36411, CoreFX 5.0.20.36411), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.0 (CoreCLR 5.0.20.36411, CoreFX 5.0.20.36411), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 528.0 ns | 5.57 ns | 4.94 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Array | Array | 100 | 191.4 ns | 1.67 ns | 1.56 ns | 0.36 | 0.00 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 166.2 ns | 1.88 ns | 1.76 ns | 0.32 | 0.00 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 215.8 ns | 2.12 ns | 1.99 ns | 0.41 | 0.00 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 737.5 ns | 6.24 ns | 5.84 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 199.4 ns | 2.30 ns | 1.92 ns | 0.27 | 0.00 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 741.2 ns | 6.95 ns | 6.50 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 233.7 ns | 3.46 ns | 3.24 ns | 0.32 | 0.00 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 737.0 ns | 6.21 ns | 5.80 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Value | List_Value | 100 | 401.4 ns | 3.81 ns | 3.18 ns | 0.54 | 0.01 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,176.1 ns | 25.71 ns | 21.47 ns | 1.00 | 0.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 331.5 ns | 3.55 ns | 3.32 ns | 0.15 | 0.00 | 0.0191 | - | - | 40 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 570.6 ns | 5.53 ns | 5.18 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 523.1 ns | 4.70 ns | 4.40 ns | 0.92 | 0.01 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 572.8 ns | 5.56 ns | 5.20 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 520.5 ns | 7.43 ns | 6.59 ns | 0.91 | 0.02 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 572.2 ns | 3.72 ns | 3.11 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 376.9 ns | 2.50 ns | 2.22 ns | 0.66 | 0.00 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,114.6 ns | 19.98 ns | 18.69 ns | 1.00 | 0.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 358.6 ns | 2.02 ns | 1.88 ns | 0.17 | 0.00 | 0.0305 | - | - | 64 B | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|--------:|--------:|------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 594.4 ns | 2.87 ns | 2.24 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Array | Array | 100 | 193.1 ns | 0.79 ns | 0.66 ns | 0.32 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 778.5 ns | 2.27 ns | 1.77 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 226.0 ns | 1.07 ns | 0.95 ns | 0.29 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 792.8 ns | 3.27 ns | 2.73 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 228.5 ns | 1.08 ns | 1.01 ns | 0.29 | - | - | - | - | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 795.6 ns | 3.95 ns | 3.69 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Value | List_Value | 100 | 783.9 ns | 8.51 ns | 7.10 ns | 0.99 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,713.6 ns | 7.04 ns | 5.88 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 248.1 ns | 1.01 ns | 0.95 ns | 0.14 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 787.9 ns | 3.26 ns | 2.89 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 779.3 ns | 6.61 ns | 5.86 ns | 0.99 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 746.7 ns | 2.31 ns | 2.16 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 806.8 ns | 3.82 ns | 3.19 ns | 1.08 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 749.4 ns | 5.37 ns | 4.49 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 728.0 ns | 1.89 ns | 1.58 ns | 0.97 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,712.4 ns | 6.90 ns | 6.45 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 296.8 ns | 5.57 ns | 4.94 ns | 0.17 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/AnyBenchmarks.md b/Benchmarks/AnyBenchmarks.md index 9d80926bb..86b323c10 100644 --- a/Benchmarks/AnyBenchmarks.md +++ b/Benchmarks/AnyBenchmarks.md @@ -4,51 +4,50 @@ [AnyBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |-----------:|----------:|----------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 8.7865 ns | 0.0358 ns | 0.0318 ns | 1.000 | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.000 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 0.5244 ns | 0.0186 ns | 0.0165 ns | 0.060 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 0.2542 ns | 0.0066 ns | 0.0059 ns | 0.029 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 20.5024 ns | 0.1154 ns | 0.1023 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 12.4688 ns | 0.0330 ns | 0.0293 ns | 0.61 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 4.8538 ns | 0.0168 ns | 0.0140 ns | 1.00 | - | - | - | - | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 4.6245 ns | 0.0119 ns | 0.0105 ns | 0.95 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 5.5336 ns | 0.0157 ns | 0.0139 ns | 1.00 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 1.7812 ns | 0.0093 ns | 0.0087 ns | 0.32 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 66.4073 ns | 0.3688 ns | 0.3080 ns | 1.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 60.3088 ns | 0.1136 ns | 0.1007 ns | 0.91 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 18.3779 ns | 0.0678 ns | 0.0634 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 10.5758 ns | 0.0991 ns | 0.0828 ns | 0.58 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 4.9100 ns | 0.0256 ns | 0.0239 ns | 1.00 | - | - | - | - | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 1.7918 ns | 0.0128 ns | 0.0107 ns | 0.36 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 5.5565 ns | 0.0178 ns | 0.0158 ns | 1.00 | - | - | - | - | -| Hyperlinq_List_Reference | List_Reference | 100 | 1.8166 ns | 0.0157 ns | 0.0139 ns | 0.33 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 62.4382 ns | 0.1938 ns | 0.1618 ns | 1.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 62.1935 ns | 0.1632 ns | 0.1363 ns | 1.00 | 0.0191 | - | - | 40 B | +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |----------:|----------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 8.522 ns | 0.1072 ns | 0.0950 ns | 8.489 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 8.337 ns | 0.1458 ns | 0.2591 ns | 8.220 ns | 0.99 | 0.04 | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 20.939 ns | 0.3606 ns | 0.3196 ns | 20.920 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 10.763 ns | 0.0420 ns | 0.0372 ns | 10.761 ns | 0.51 | 0.01 | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 4.172 ns | 0.0261 ns | 0.0232 ns | 4.170 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 8.238 ns | 0.0348 ns | 0.0308 ns | 8.232 ns | 1.97 | 0.02 | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 5.244 ns | 0.0159 ns | 0.0141 ns | 5.245 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 1.570 ns | 0.0114 ns | 0.0101 ns | 1.570 ns | 0.30 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 56.214 ns | 0.3040 ns | 0.2539 ns | 56.183 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 50.317 ns | 0.1716 ns | 0.1433 ns | 50.332 ns | 0.90 | 0.01 | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 20.843 ns | 0.2172 ns | 0.1814 ns | 20.827 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 13.088 ns | 0.0794 ns | 0.0704 ns | 13.070 ns | 0.63 | 0.01 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 4.156 ns | 0.0202 ns | 0.0189 ns | 4.153 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 1.564 ns | 0.0159 ns | 0.0141 ns | 1.562 ns | 0.38 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 5.329 ns | 0.1381 ns | 0.1224 ns | 5.288 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_List_Reference | List_Reference | 100 | 1.811 ns | 0.0220 ns | 0.0195 ns | 1.804 ns | 0.34 | 0.01 | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 56.362 ns | 0.1850 ns | 0.1640 ns | 56.408 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 54.655 ns | 0.1620 ns | 0.1436 ns | 54.680 ns | 0.97 | 0.00 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/AnyPredicateBenchmarks.md b/Benchmarks/AnyPredicateBenchmarks.md index 9ef69d1eb..c579f5e28 100644 --- a/Benchmarks/AnyPredicateBenchmarks.md +++ b/Benchmarks/AnyPredicateBenchmarks.md @@ -4,51 +4,50 @@ [AnyPredicateBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyPredicateBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` | Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | |------------------------------------ |-------------------------- |------ |------------:|---------:|---------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 557.44 ns | 1.160 ns | 1.028 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Array | Array | 100 | 187.98 ns | 0.259 ns | 0.230 ns | 0.34 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 189.53 ns | 0.548 ns | 0.458 ns | 0.34 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 190.13 ns | 0.451 ns | 0.422 ns | 0.34 | - | - | - | - | +| Linq_Array | Array | 100 | 552.35 ns | 3.072 ns | 2.873 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Array | Array | 100 | 193.02 ns | 0.522 ns | 0.488 ns | 0.35 | - | - | - | - | | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 739.29 ns | 1.522 ns | 1.349 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 203.08 ns | 0.430 ns | 0.359 ns | 0.27 | - | - | - | - | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 728.49 ns | 1.738 ns | 1.540 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 227.33 ns | 1.183 ns | 1.107 ns | 0.31 | - | - | - | - | | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 737.14 ns | 1.366 ns | 1.211 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 241.16 ns | 0.724 ns | 0.677 ns | 0.33 | - | - | - | - | +| Linq_Collection_Value | Collection_Value | 100 | 773.24 ns | 2.739 ns | 2.287 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 231.23 ns | 0.944 ns | 0.837 ns | 0.30 | - | - | - | - | | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 738.33 ns | 1.090 ns | 1.020 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Value | List_Value | 100 | 393.22 ns | 0.587 ns | 0.549 ns | 0.53 | - | - | - | - | +| Linq_List_Value | List_Value | 100 | 781.35 ns | 6.770 ns | 6.001 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Value | List_Value | 100 | 787.16 ns | 6.048 ns | 4.722 ns | 1.01 | 0.0153 | - | - | 32 B | | | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,142.07 ns | 4.926 ns | 4.607 ns | 1.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 80.78 ns | 0.161 ns | 0.150 ns | 0.04 | - | - | - | - | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,719.18 ns | 4.384 ns | 3.661 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 74.65 ns | 0.616 ns | 0.546 ns | 0.04 | - | - | - | - | | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 581.65 ns | 0.687 ns | 0.609 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 585.81 ns | 2.005 ns | 1.674 ns | 1.01 | 0.0153 | - | - | 32 B | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 776.80 ns | 3.107 ns | 2.906 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 786.45 ns | 6.334 ns | 5.615 ns | 1.01 | 0.0153 | - | - | 32 B | | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 585.45 ns | 4.103 ns | 3.426 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 535.46 ns | 1.845 ns | 1.725 ns | 0.91 | 0.0153 | - | - | 32 B | +| Linq_Collection_Reference | Collection_Reference | 100 | 730.96 ns | 4.551 ns | 4.257 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 764.02 ns | 7.369 ns | 6.153 ns | 1.05 | 0.0153 | - | - | 32 B | | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 515.11 ns | 1.186 ns | 1.109 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 349.71 ns | 0.985 ns | 0.873 ns | 0.68 | - | - | - | - | +| Linq_List_Reference | List_Reference | 100 | 735.80 ns | 4.364 ns | 3.868 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 741.53 ns | 3.903 ns | 3.259 ns | 1.01 | 0.0153 | - | - | 32 B | | | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,060.41 ns | 4.440 ns | 3.936 ns | 1.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 86.05 ns | 0.537 ns | 0.449 ns | 0.04 | 0.0191 | - | - | 40 B | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,717.84 ns | 3.838 ns | 3.402 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 77.00 ns | 1.529 ns | 1.761 ns | 0.05 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/ArrayIterationBenchmarks.md b/Benchmarks/ArrayIterationBenchmarks.md index 9f43bfd0b..0385d6cc1 100644 --- a/Benchmarks/ArrayIterationBenchmarks.md +++ b/Benchmarks/ArrayIterationBenchmarks.md @@ -4,33 +4,35 @@ [ArrayIterationBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ArrayIterationBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Count | Mean | Error | StdDev | Ratio | RatioSD | -|----------------------------- |--------- |----------:|----------:|----------:|------:|--------:| -| Foreach | 10000000 | 5.994 ms | 0.1155 ms | 0.1024 ms | 1.00 | 0.00 | -| For | 10000000 | 4.917 ms | 0.0722 ms | 0.0675 ms | 0.82 | 0.02 | -| For_Unsafe | 10000000 | 6.019 ms | 0.0699 ms | 0.0654 ms | 1.01 | 0.02 | -| ForAdamczewski | 10000000 | 4.764 ms | 0.0291 ms | 0.0272 ms | 0.80 | 0.02 | -| ForAdamczewskiUnsafe | 10000000 | 4.169 ms | 0.0829 ms | 0.0921 ms | 0.70 | 0.03 | -| Span | 10000000 | 4.720 ms | 0.0553 ms | 0.0491 ms | 0.79 | 0.02 | -| Memory | 10000000 | 6.107 ms | 0.0278 ms | 0.0260 ms | 1.02 | 0.02 | -| ArraySegment_Foreach | 10000000 | 28.274 ms | 0.0372 ms | 0.0311 ms | 4.73 | 0.08 | -| ArraySegment_For | 10000000 | 5.948 ms | 0.0457 ms | 0.0381 ms | 0.99 | 0.02 | -| ArraySegment_Wrapper_Foreach | 10000000 | 6.136 ms | 0.0263 ms | 0.0219 ms | 1.03 | 0.02 | +| Method | Count | Mean | Error | StdDev | Ratio | RatioSD | Allocated | +|--------------------- |-------- |-----------:|---------:|---------:|-------------:|--------:|----------:| +| Foreach | 1000000 | 459.6 μs | 2.49 μs | 1.95 μs | baseline | | 13 B | +| For | 1000000 | 460.4 μs | 2.37 μs | 2.21 μs | 1.00x slower | 0.01x | - | +| For_Unsafe | 1000000 | 460.7 μs | 2.86 μs | 2.54 μs | 1.00x slower | 0.00x | - | +| ForAdamczewski | 1000000 | 386.4 μs | 2.78 μs | 2.60 μs | 1.19x faster | 0.01x | - | +| ForAdamczewskiUnsafe | 1000000 | 387.7 μs | 4.10 μs | 3.84 μs | 1.18x faster | 0.01x | - | +| Span | 1000000 | 460.5 μs | 2.08 μs | 1.85 μs | 1.00x slower | 0.01x | - | +| ArraySegment_Foreach | 1000000 | 1,746.3 μs | 12.53 μs | 11.72 μs | 3.80x slower | 0.02x | 1 B | +| ArraySegment_For | 1000000 | 646.1 μs | 7.65 μs | 6.39 μs | 1.41x slower | 0.01x | - | +| ArraySegment_AsSpan | 1000000 | 461.5 μs | 3.82 μs | 3.19 μs | 1.00x slower | 0.01x | 1 B | +| ArraySegment_AsArray | 1000000 | 626.8 μs | 3.41 μs | 3.03 μs | 1.36x slower | 0.01x | 1 B | +| Vector | 1000000 | 119.9 μs | 1.72 μs | 1.61 μs | 3.83x faster | 0.06x | - | diff --git a/Benchmarks/ArrayToArrayBenchmarks.md b/Benchmarks/ArrayToArrayBenchmarks.md new file mode 100644 index 000000000..08614ccc0 --- /dev/null +++ b/Benchmarks/ArrayToArrayBenchmarks.md @@ -0,0 +1,41 @@ +## ArrayToArrayBenchmarks + +### Source +[ArrayToArrayBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ArrayToArrayBenchmarks.cs) + +### References: +- Linq: 6.0.0-preview.7.21377.19 +- System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) +- System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) +- System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) + +### Results: +``` ini + +BenchmarkDotNet=v0.13.0.1561-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 + +``` +| Method | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|----------------- |------ |----------:|---------:|---------:|-------------:|--------:|-------:|------:|------:|----------:| +| **ArrayClone** | **10** | **106.79 ns** | **0.520 ns** | **0.486 ns** | **baseline** | **** | **0.0305** | **-** | **-** | **64 B** | +| SpanToArray | 10 | 11.76 ns | 0.116 ns | 0.097 ns | 9.08x faster | 0.09x | 0.0306 | - | - | 64 B | +| SpanCopyTo | 10 | 12.71 ns | 0.228 ns | 0.213 ns | 8.41x faster | 0.15x | 0.0306 | - | - | 64 B | +| CollectionCopyTo | 10 | 16.74 ns | 0.099 ns | 0.093 ns | 6.38x faster | 0.04x | 0.0306 | - | - | 64 B | +| | | | | | | | | | | | +| **ArrayClone** | **100** | **115.18 ns** | **0.865 ns** | **0.810 ns** | **baseline** | **** | **0.2019** | **-** | **-** | **424 B** | +| SpanToArray | 100 | 38.58 ns | 0.355 ns | 0.297 ns | 2.98x faster | 0.03x | 0.2027 | - | - | 424 B | +| SpanCopyTo | 100 | 40.01 ns | 0.462 ns | 0.432 ns | 2.88x faster | 0.03x | 0.2027 | - | - | 424 B | +| CollectionCopyTo | 100 | 43.68 ns | 0.381 ns | 0.356 ns | 2.64x faster | 0.03x | 0.2027 | - | - | 424 B | +| | | | | | | | | | | | +| **ArrayClone** | **1000** | **310.98 ns** | **3.725 ns** | **3.302 ns** | **baseline** | **** | **1.9155** | **-** | **-** | **4,024 B** | +| SpanToArray | 1000 | 308.84 ns | 1.502 ns | 1.254 ns | 1.01x faster | 0.01x | 1.9226 | - | - | 4,024 B | +| SpanCopyTo | 1000 | 295.58 ns | 5.032 ns | 4.707 ns | 1.05x faster | 0.01x | 1.9155 | - | - | 4,024 B | +| CollectionCopyTo | 1000 | 299.15 ns | 3.317 ns | 3.102 ns | 1.04x faster | 0.01x | 1.9155 | - | - | 4,024 B | diff --git a/Benchmarks/ContainsBenchmarks.md b/Benchmarks/ContainsBenchmarks.md index 1de327e5b..b079eda6c 100644 --- a/Benchmarks/ContainsBenchmarks.md +++ b/Benchmarks/ContainsBenchmarks.md @@ -4,28 +4,51 @@ [ContainsBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsBenchmarks.cs) ### References: -- Linq: 5.0.2 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta34](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta34) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores -.NET Core SDK=5.0.200-preview.20614.14 - [Host] : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.0.1561-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + Job-PWZZUK : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 Categories=Array +Runtime=.NET 6.0 ``` -| Method | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|-------------------- |------ |---------:|---------:|---------:|------:|--------:|------:|------:|------:|----------:| -| Linq_Array | 100 | 55.27 ns | 1.138 ns | 1.479 ns | 1.00 | 0.00 | - | - | - | - | -| Hyperlinq_Array | 100 | 49.53 ns | 1.536 ns | 4.528 ns | 0.89 | 0.04 | - | - | - | - | -| Hyperlinq_Span | 100 | 96.52 ns | 1.965 ns | 3.442 ns | 1.76 | 0.09 | - | - | - | - | -| Hyperlinq_Span_SIMD | 100 | 19.46 ns | 0.264 ns | 0.449 ns | 0.35 | 0.01 | - | - | - | - | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |------------:|----------:|----------:|-------------:|--------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 40.84 ns | 0.155 ns | 0.137 ns | baseline | | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 39.48 ns | 0.544 ns | 0.509 ns | 1.04x faster | 0.01x | - | - | - | - | +| Hyperlinq_Array_SIMD | Array | 100 | 24.73 ns | 0.106 ns | 0.094 ns | 1.65x faster | 0.01x | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 698.87 ns | 4.071 ns | 3.808 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 131.79 ns | 0.836 ns | 0.699 ns | 5.30x faster | 0.04x | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 41.31 ns | 0.190 ns | 0.178 ns | baseline | | - | - | - | - | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 48.15 ns | 0.182 ns | 0.161 ns | 1.17x slower | 0.01x | - | - | - | - | +| | | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 42.47 ns | 0.369 ns | 0.327 ns | baseline | | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 48.39 ns | 0.315 ns | 0.263 ns | 1.14x slower | 0.01x | - | - | - | - | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,117.62 ns | 24.109 ns | 22.552 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,065.50 ns | 3.295 ns | 2.572 ns | 1.99x faster | 0.02x | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 701.55 ns | 11.099 ns | 9.839 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 723.25 ns | 3.170 ns | 2.965 ns | 1.03x slower | 0.01x | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 44.63 ns | 0.412 ns | 0.344 ns | baseline | | - | - | - | - | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 46.06 ns | 0.179 ns | 0.140 ns | 1.03x slower | 0.01x | - | - | - | - | +| | | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 44.93 ns | 0.386 ns | 0.342 ns | baseline | | - | - | - | - | +| Hyperlinq_List_Reference | List_Reference | 100 | 47.14 ns | 0.188 ns | 0.167 ns | 1.05x slower | 0.01x | - | - | - | - | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,104.73 ns | 7.920 ns | 6.183 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,061.42 ns | 4.170 ns | 3.697 ns | 1.02x faster | 0.00x | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/ContainsComparerBenchmarks.md b/Benchmarks/ContainsComparerBenchmarks.md index 7d6ad1322..16391d05b 100644 --- a/Benchmarks/ContainsComparerBenchmarks.md +++ b/Benchmarks/ContainsComparerBenchmarks.md @@ -4,49 +4,50 @@ [ContainsComparerBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsComparerBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.0.1561-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + Job-AXHCLI : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------- |-------------------------- |------ |-----------:|--------:|--------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 568.2 ns | 2.19 ns | 2.05 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Array | Array | 100 | 241.1 ns | 0.68 ns | 0.60 ns | 0.42 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 192.6 ns | 0.76 ns | 0.71 ns | 0.34 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 219.4 ns | 0.81 ns | 0.72 ns | 0.39 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 744.5 ns | 1.64 ns | 1.37 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 257.5 ns | 0.97 ns | 0.91 ns | 0.35 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 772.5 ns | 1.48 ns | 1.32 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 254.0 ns | 0.42 ns | 0.38 ns | 0.33 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 743.8 ns | 1.89 ns | 1.68 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Value | List_Value | 100 | 401.6 ns | 0.75 ns | 0.62 ns | 0.54 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,139.1 ns | 5.52 ns | 4.61 ns | 1.00 | 0.0191 | - | - | 40 B | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 563.4 ns | 1.60 ns | 1.25 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 564.5 ns | 1.90 ns | 1.78 ns | 1.00 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 563.9 ns | 2.11 ns | 1.87 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 565.1 ns | 1.37 ns | 1.22 ns | 1.00 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 562.8 ns | 1.59 ns | 1.41 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 376.3 ns | 1.97 ns | 1.75 ns | 0.67 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,030.0 ns | 3.80 ns | 3.37 ns | 1.00 | 0.0191 | - | - | 40 B | +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |------------:|-----------:|-----------:|------------:|--------------:|--------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 1,048.66 ns | 107.295 ns | 316.361 ns | 903.87 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_Array | Array | 100 | 268.14 ns | 2.061 ns | 1.827 ns | 267.28 ns | 4.81x faster | 1.19x | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 881.92 ns | 6.470 ns | 5.735 ns | 880.29 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 302.87 ns | 1.992 ns | 1.864 ns | 302.07 ns | 2.91x faster | 0.03x | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 938.13 ns | 9.760 ns | 9.129 ns | 936.36 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 48.95 ns | 0.239 ns | 0.212 ns | 48.90 ns | 19.18x faster | 0.20x | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 933.26 ns | 9.635 ns | 8.046 ns | 929.66 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Value | List_Value | 100 | 48.66 ns | 0.173 ns | 0.144 ns | 48.65 ns | 19.18x faster | 0.20x | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,158.84 ns | 9.131 ns | 8.542 ns | 2,155.35 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,191.03 ns | 3.012 ns | 2.670 ns | 1,189.75 ns | 1.81x faster | 0.01x | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 882.52 ns | 5.452 ns | 4.833 ns | 881.50 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 857.25 ns | 3.404 ns | 2.842 ns | 856.86 ns | 1.03x faster | 0.01x | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 889.74 ns | 13.979 ns | 12.392 ns | 887.60 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 47.00 ns | 0.515 ns | 0.457 ns | 46.82 ns | 18.93x faster | 0.31x | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 932.31 ns | 6.806 ns | 5.314 ns | 930.35 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 47.98 ns | 0.277 ns | 0.217 ns | 47.97 ns | 19.43x faster | 0.10x | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,159.99 ns | 7.158 ns | 6.695 ns | 2,158.15 ns | baseline | | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,157.65 ns | 6.057 ns | 5.369 ns | 2,156.09 ns | 1.00x faster | 0.00x | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/CountBenchmarks.md b/Benchmarks/CountBenchmarks.md index 2f898d4bb..887ed8a21 100644 --- a/Benchmarks/CountBenchmarks.md +++ b/Benchmarks/CountBenchmarks.md @@ -4,58 +4,57 @@ [CountBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/CountBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` | Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | |------------------------------------ |-------------------------- |------ |--------------:|----------:|----------:|-------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 8.9989 ns | 0.0181 ns | 0.0141 ns | 1.000 | 0.00 | - | - | - | - | -| StructLinq_Array | Array | 100 | 0.9332 ns | 0.0091 ns | 0.0081 ns | 0.104 | 0.00 | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.000 | 0.00 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 0.2514 ns | 0.0047 ns | 0.0041 ns | 0.028 | 0.00 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.000 | 0.00 | - | - | - | - | +| Linq_Array | Array | 100 | 8.6538 ns | 0.0562 ns | 0.0498 ns | 1.00 | 0.00 | - | - | - | - | +| StructLinq_Array | Array | 100 | 0.7170 ns | 0.0126 ns | 0.0112 ns | 0.08 | 0.00 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 7.9852 ns | 0.0270 ns | 0.0253 ns | 0.92 | 0.01 | - | - | - | - | | | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 339.9804 ns | 0.7672 ns | 0.6801 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 591.7192 ns | 1.8374 ns | 1.6288 ns | 1.74 | 0.01 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 147.5369 ns | 0.3168 ns | 0.2963 ns | 0.43 | 0.00 | - | - | - | - | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 349.4069 ns | 2.8233 ns | 2.3575 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 619.7720 ns | 4.5373 ns | 4.0222 ns | 1.77 | 0.01 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 140.7260 ns | 0.2846 ns | 0.2523 ns | 0.40 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 4.6490 ns | 0.0391 ns | 0.0305 ns | 1.00 | 0.00 | - | - | - | - | -| StructLinq_Collection_Value | Collection_Value | 100 | 619.6203 ns | 0.9017 ns | 0.7530 ns | 133.29 | 0.89 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 4.1855 ns | 0.0207 ns | 0.0184 ns | 0.90 | 0.01 | - | - | - | - | +| Linq_Collection_Value | Collection_Value | 100 | 4.1117 ns | 0.0213 ns | 0.0199 ns | 1.00 | 0.00 | - | - | - | - | +| StructLinq_Collection_Value | Collection_Value | 100 | 618.7262 ns | 3.1791 ns | 2.6547 ns | 150.49 | 0.88 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 7.5543 ns | 0.0264 ns | 0.0247 ns | 1.84 | 0.01 | - | - | - | - | | | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 5.3257 ns | 0.0091 ns | 0.0085 ns | 1.00 | 0.00 | - | - | - | - | -| StructLinq_List_Value | List_Value | 100 | 2.3656 ns | 0.0092 ns | 0.0086 ns | 0.44 | 0.00 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 1.5443 ns | 0.0211 ns | 0.0176 ns | 0.29 | 0.00 | - | - | - | - | +| Linq_List_Value | List_Value | 100 | 4.9752 ns | 0.0545 ns | 0.0483 ns | 1.00 | 0.00 | - | - | - | - | +| StructLinq_List_Value | List_Value | 100 | 2.3856 ns | 0.0229 ns | 0.0214 ns | 0.48 | 0.01 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 1.6012 ns | 0.0116 ns | 0.0109 ns | 0.32 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,041.1344 ns | 3.3812 ns | 2.8234 ns | 1.00 | 0.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,187.2774 ns | 1.6964 ns | 1.5038 ns | 0.58 | 0.00 | - | - | - | - | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,624.5794 ns | 6.4122 ns | 5.6842 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 778.0014 ns | 2.2398 ns | 1.9856 ns | 0.48 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 248.8358 ns | 1.4702 ns | 1.3033 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 384.4841 ns | 2.5870 ns | 2.1603 ns | 1.55 | 0.01 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 254.0431 ns | 0.7041 ns | 0.5880 ns | 1.02 | 0.01 | 0.0153 | - | - | 32 B | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 345.5721 ns | 1.6528 ns | 1.3802 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 622.3207 ns | 6.1665 ns | 5.4665 ns | 1.80 | 0.02 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 399.7432 ns | 3.6850 ns | 3.0771 ns | 1.16 | 0.01 | 0.0153 | - | - | 32 B | | | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 4.6522 ns | 0.0152 ns | 0.0127 ns | 1.00 | 0.00 | - | - | - | - | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 383.2519 ns | 0.8476 ns | 0.7928 ns | 82.37 | 0.32 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 1.5303 ns | 0.0101 ns | 0.0090 ns | 0.33 | 0.00 | - | - | - | - | +| Linq_Collection_Reference | Collection_Reference | 100 | 4.1547 ns | 0.0307 ns | 0.0272 ns | 1.00 | 0.00 | - | - | - | - | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 617.2308 ns | 1.6776 ns | 1.4871 ns | 148.57 | 1.08 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 1.7886 ns | 0.0117 ns | 0.0104 ns | 0.43 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 5.4791 ns | 0.0141 ns | 0.0125 ns | 1.00 | 0.00 | - | - | - | - | -| StructLinq_List_Reference | List_Reference | 100 | 383.6696 ns | 0.7411 ns | 0.6932 ns | 70.01 | 0.20 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 1.5162 ns | 0.0048 ns | 0.0043 ns | 0.28 | 0.00 | - | - | - | - | +| Linq_List_Reference | List_Reference | 100 | 4.9597 ns | 0.0286 ns | 0.0268 ns | 1.00 | 0.00 | - | - | - | - | +| StructLinq_List_Reference | List_Reference | 100 | 620.5949 ns | 3.4575 ns | 3.2342 ns | 125.13 | 0.90 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 1.7393 ns | 0.0310 ns | 0.0275 ns | 0.35 | 0.01 | - | - | - | - | | | | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,948.7201 ns | 7.2494 ns | 6.0535 ns | 1.00 | 0.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,786.5839 ns | 2.9349 ns | 2.6017 ns | 0.92 | 0.00 | 0.0191 | - | - | 40 B | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,630.2851 ns | 4.5997 ns | 4.3025 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,419.2966 ns | 3.7573 ns | 3.3308 ns | 0.87 | 0.00 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/DistinctBenchmarks.md b/Benchmarks/DistinctBenchmarks.md index 18a3b1bee..0195213ec 100644 --- a/Benchmarks/DistinctBenchmarks.md +++ b/Benchmarks/DistinctBenchmarks.md @@ -4,58 +4,59 @@ [DistinctBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/DistinctBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |---------:|----------:|----------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 2.909 μs | 0.0101 μs | 0.0094 μs | 1.00 | 2.0599 | - | - | 4312 B | -| StructLinq_Array | Array | 100 | 2.459 μs | 0.0091 μs | 0.0076 μs | 0.84 | 1.4000 | - | - | 2928 B | -| Hyperlinq_Array | Array | 100 | 1.601 μs | 0.0039 μs | 0.0037 μs | 0.55 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 1.557 μs | 0.0034 μs | 0.0032 μs | 0.54 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 1.669 μs | 0.0026 μs | 0.0023 μs | 0.57 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 3.190 μs | 0.0064 μs | 0.0057 μs | 1.00 | 2.0599 | - | - | 4312 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 2.272 μs | 0.0076 μs | 0.0067 μs | 0.71 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 1.651 μs | 0.0029 μs | 0.0026 μs | 0.52 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 3.170 μs | 0.0118 μs | 0.0105 μs | 1.00 | 2.0599 | - | - | 4312 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 2.245 μs | 0.0123 μs | 0.0115 μs | 0.71 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 1.575 μs | 0.0047 μs | 0.0044 μs | 0.50 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 3.214 μs | 0.0092 μs | 0.0086 μs | 1.00 | 2.0599 | - | - | 4312 B | -| StructLinq_List_Value | List_Value | 100 | 1.445 μs | 0.0041 μs | 0.0034 μs | 0.45 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 1.922 μs | 0.0041 μs | 0.0036 μs | 0.60 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 7.912 μs | 0.0213 μs | 0.0189 μs | 1.00 | 2.0905 | - | - | 4400 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 4.850 μs | 0.0157 μs | 0.0131 μs | 0.61 | 0.0305 | - | - | 72 B | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 2.891 μs | 0.0121 μs | 0.0113 μs | 1.00 | 2.0599 | - | - | 4312 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 1.594 μs | 0.0035 μs | 0.0031 μs | 0.55 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 2.134 μs | 0.0053 μs | 0.0049 μs | 0.74 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 2.885 μs | 0.0106 μs | 0.0094 μs | 1.00 | 2.0599 | - | - | 4312 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 1.584 μs | 0.0026 μs | 0.0024 μs | 0.55 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 2.126 μs | 0.0089 μs | 0.0083 μs | 0.74 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 2.869 μs | 0.0117 μs | 0.0098 μs | 1.00 | 2.0599 | - | - | 4312 B | -| StructLinq_List_Reference | List_Reference | 100 | 1.589 μs | 0.0053 μs | 0.0047 μs | 0.55 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 1.879 μs | 0.0047 μs | 0.0042 μs | 0.65 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 7.882 μs | 0.0441 μs | 0.0368 μs | 1.00 | 2.0905 | - | - | 4400 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 5.114 μs | 0.0120 μs | 0.0113 μs | 0.65 | 0.0534 | - | - | 112 B | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |---------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 1.762 μs | 0.0060 μs | 0.0050 μs | 1.00 | 0.00 | 1.3294 | - | - | 2,784 B | +| StructLinq_Array | Array | 100 | 1.253 μs | 0.0074 μs | 0.0061 μs | 0.71 | 0.00 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 1.468 μs | 0.0061 μs | 0.0054 μs | 0.83 | 0.00 | - | - | - | - | +| Hyperlinq_Span | Array | 100 | 1.546 μs | 0.0082 μs | 0.0076 μs | 0.88 | 0.00 | - | - | - | - | +| Hyperlinq_Memory | Array | 100 | 1.561 μs | 0.0080 μs | 0.0071 μs | 0.89 | 0.01 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 2.381 μs | 0.0472 μs | 0.0775 μs | 1.00 | 0.00 | 1.3275 | - | - | 2,784 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 2.206 μs | 0.0220 μs | 0.0206 μs | 0.95 | 0.04 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 1.495 μs | 0.0074 μs | 0.0069 μs | 0.65 | 0.02 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 2.249 μs | 0.0102 μs | 0.0096 μs | 1.00 | 0.00 | 1.3275 | - | - | 2,784 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 2.210 μs | 0.0175 μs | 0.0163 μs | 0.98 | 0.01 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 1.472 μs | 0.0064 μs | 0.0053 μs | 0.65 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 2.305 μs | 0.0117 μs | 0.0104 μs | 1.00 | 0.00 | 1.3275 | - | - | 2,784 B | +| StructLinq_List_Value | List_Value | 100 | 1.490 μs | 0.0110 μs | 0.0102 μs | 0.65 | 0.00 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 2.725 μs | 0.0121 μs | 0.0113 μs | 1.18 | 0.01 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 7.732 μs | 0.0411 μs | 0.0364 μs | 1.00 | 0.00 | 2.0599 | - | - | 4,320 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 4.331 μs | 0.0281 μs | 0.0263 μs | 0.56 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 2.316 μs | 0.0227 μs | 0.0189 μs | 1.00 | 0.00 | 1.3275 | - | - | 2,784 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 2.209 μs | 0.0186 μs | 0.0174 μs | 0.95 | 0.01 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 2.636 μs | 0.0155 μs | 0.0137 μs | 1.14 | 0.01 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 2.250 μs | 0.0091 μs | 0.0085 μs | 1.00 | 0.00 | 1.3275 | - | - | 2,784 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 2.199 μs | 0.0201 μs | 0.0188 μs | 0.98 | 0.01 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 2.661 μs | 0.0150 μs | 0.0125 μs | 1.18 | 0.01 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 2.307 μs | 0.0134 μs | 0.0119 μs | 1.00 | 0.00 | 1.3275 | - | - | 2,784 B | +| StructLinq_List_Reference | List_Reference | 100 | 2.175 μs | 0.0134 μs | 0.0125 μs | 0.94 | 0.01 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 2.781 μs | 0.0236 μs | 0.0209 μs | 1.21 | 0.01 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 7.339 μs | 0.1288 μs | 0.1888 μs | 1.00 | 0.00 | 2.0599 | - | - | 4,320 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 5.030 μs | 0.0163 μs | 0.0152 μs | 0.68 | 0.02 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/ElementAtBenchmarks.md b/Benchmarks/ElementAtBenchmarks.md index 6710af6c0..f0ec761d7 100644 --- a/Benchmarks/ElementAtBenchmarks.md +++ b/Benchmarks/ElementAtBenchmarks.md @@ -4,49 +4,50 @@ [ElementAtBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ElementAtBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------- |-------------------------- |------ |-------------:|----------:|----------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 23.360 ns | 0.0504 ns | 0.0447 ns | 1.00 | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 5.306 ns | 0.0090 ns | 0.0084 ns | 0.23 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 5.032 ns | 0.0040 ns | 0.0031 ns | 0.22 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 6.595 ns | 0.0121 ns | 0.0113 ns | 0.28 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 359.232 ns | 0.5723 ns | 0.4779 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 137.595 ns | 0.2246 ns | 0.1991 ns | 0.38 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 317.957 ns | 5.4123 ns | 4.5195 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 143.821 ns | 0.2611 ns | 0.2443 ns | 0.45 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 10.390 ns | 0.0256 ns | 0.0227 ns | 1.00 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 6.672 ns | 0.0243 ns | 0.0215 ns | 0.64 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,078.866 ns | 4.3966 ns | 4.1125 ns | 1.00 | 0.0191 | - | - | 40 B | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 231.469 ns | 0.3659 ns | 0.3243 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 241.359 ns | 1.1134 ns | 1.0415 ns | 1.04 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 231.936 ns | 0.3911 ns | 0.3659 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 255.067 ns | 0.8164 ns | 0.7237 ns | 1.10 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 10.386 ns | 0.0318 ns | 0.0282 ns | 1.00 | - | - | - | - | -| Hyperlinq_List_Reference | List_Reference | 100 | 6.670 ns | 0.0148 ns | 0.0132 ns | 0.64 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,945.874 ns | 4.9947 ns | 4.4276 ns | 1.00 | 0.0191 | - | - | 40 B | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |-------------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 16.456 ns | 0.0966 ns | 0.0904 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 12.952 ns | 0.0361 ns | 0.0320 ns | 0.79 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 321.772 ns | 2.7943 ns | 2.6138 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 131.436 ns | 0.4074 ns | 0.3611 ns | 0.41 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 320.549 ns | 5.2212 ns | 4.6284 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 136.995 ns | 0.5484 ns | 0.4861 ns | 0.43 | 0.01 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 9.673 ns | 0.0693 ns | 0.0648 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 330.177 ns | 2.9100 ns | 2.5796 ns | 34.15 | 0.38 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,620.433 ns | 4.6504 ns | 4.1224 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 805.497 ns | 3.5011 ns | 3.1036 ns | 0.50 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 322.075 ns | 1.6159 ns | 1.4324 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 335.420 ns | 2.7009 ns | 2.2554 ns | 1.04 | 0.01 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 319.994 ns | 3.3920 ns | 3.0069 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 364.654 ns | 1.4024 ns | 1.2432 ns | 1.14 | 0.01 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 9.695 ns | 0.0674 ns | 0.0527 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_List_Reference | List_Reference | 100 | 328.172 ns | 1.9735 ns | 1.6480 ns | 33.84 | 0.28 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,627.227 ns | 6.8413 ns | 6.0646 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,412.723 ns | 7.4225 ns | 6.5799 ns | 0.87 | 0.00 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/EmptyBenchmarks.md b/Benchmarks/EmptyBenchmarks.md index bd0c0f3c9..665678723 100644 --- a/Benchmarks/EmptyBenchmarks.md +++ b/Benchmarks/EmptyBenchmarks.md @@ -4,28 +4,29 @@ [EmptyBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/EmptyBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|---------------------- |------------ |----------:|----------:|----------:|------:|------:|------:|------:|----------:| -| Linq_Empty | Empty | 6.261 ns | 0.0193 ns | 0.0151 ns | 1.00 | - | - | - | - | -| Hyperlinq_Empty | Empty | 1.429 ns | 0.0070 ns | 0.0054 ns | 0.23 | - | - | - | - | -| | | | | | | | | | | -| Linq_Empty_Async | Empty_Async | 40.172 ns | 0.0809 ns | 0.0717 ns | 1.00 | - | - | - | - | -| Hyperlinq_Empty_Async | Empty_Async | 21.537 ns | 0.0361 ns | 0.0282 ns | 0.54 | - | - | - | - | +| Method | Categories | Mean | Error | StdDev | Median | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|---------------------- |------------ |-----------:|----------:|----------:|-----------:|------:|------:|------:|------:|----------:| +| Linq_Empty | Empty | 6.4057 ns | 0.0357 ns | 0.0316 ns | 6.4039 ns | 1.000 | - | - | - | - | +| Hyperlinq_Empty | Empty | 0.0060 ns | 0.0064 ns | 0.0053 ns | 0.0044 ns | 0.001 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Empty_Async | Empty_Async | 39.8805 ns | 0.1600 ns | 0.1418 ns | 39.8955 ns | 1.00 | - | - | - | - | +| Hyperlinq_Empty_Async | Empty_Async | 20.9157 ns | 0.0982 ns | 0.0871 ns | 20.9092 ns | 0.52 | - | - | - | - | diff --git a/Benchmarks/FirstBenchmarks.md b/Benchmarks/FirstBenchmarks.md index 7838c85ea..32a10096e 100644 --- a/Benchmarks/FirstBenchmarks.md +++ b/Benchmarks/FirstBenchmarks.md @@ -4,49 +4,50 @@ [FirstBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/FirstBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------- |-------------------------- |------ |-----------:|----------:|----------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 21.426 ns | 0.0585 ns | 0.0547 ns | 1.00 | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 4.999 ns | 0.0220 ns | 0.0195 ns | 0.23 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 5.013 ns | 0.0061 ns | 0.0054 ns | 0.23 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 6.534 ns | 0.0105 ns | 0.0093 ns | 0.30 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 23.940 ns | 0.0419 ns | 0.0350 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 14.134 ns | 0.0313 ns | 0.0277 ns | 0.59 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 25.161 ns | 0.0654 ns | 0.0611 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 15.751 ns | 0.0248 ns | 0.0220 ns | 0.63 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 12.900 ns | 0.0202 ns | 0.0179 ns | 1.00 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 7.295 ns | 0.0195 ns | 0.0183 ns | 0.57 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 115.584 ns | 0.2322 ns | 0.1939 ns | 1.00 | 0.0191 | - | - | 40 B | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 20.376 ns | 0.0777 ns | 0.0689 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 24.218 ns | 0.0607 ns | 0.0538 ns | 1.19 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 21.360 ns | 0.0450 ns | 0.0399 ns | 1.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 16.310 ns | 0.1366 ns | 0.1066 ns | 0.76 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 12.909 ns | 0.0265 ns | 0.0222 ns | 1.00 | - | - | - | - | -| Hyperlinq_List_Reference | List_Reference | 100 | 7.257 ns | 0.0133 ns | 0.0111 ns | 0.56 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 111.250 ns | 0.1898 ns | 0.1776 ns | 1.00 | 0.0191 | - | - | 40 B | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 22.02 ns | 0.200 ns | 0.187 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 13.20 ns | 0.042 ns | 0.038 ns | 0.60 | 0.01 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 27.38 ns | 0.087 ns | 0.073 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 16.20 ns | 0.039 ns | 0.035 ns | 0.59 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 26.56 ns | 0.153 ns | 0.136 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 18.73 ns | 0.053 ns | 0.047 ns | 0.71 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 12.36 ns | 0.055 ns | 0.046 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 22.47 ns | 0.132 ns | 0.117 ns | 1.82 | 0.01 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 109.50 ns | 0.948 ns | 0.887 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 62.59 ns | 0.160 ns | 0.141 ns | 0.57 | 0.01 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 25.50 ns | 0.148 ns | 0.139 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 18.66 ns | 0.147 ns | 0.123 ns | 0.73 | 0.01 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 26.59 ns | 0.091 ns | 0.076 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 18.75 ns | 0.119 ns | 0.105 ns | 0.71 | 0.00 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 12.40 ns | 0.064 ns | 0.060 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_List_Reference | List_Reference | 100 | 23.48 ns | 0.499 ns | 0.594 ns | 1.88 | 0.06 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 106.75 ns | 0.246 ns | 0.219 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 68.68 ns | 0.392 ns | 0.367 ns | 0.64 | 0.00 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/IterationBenchmarks.md b/Benchmarks/IterationBenchmarks.md deleted file mode 100644 index e728f5c75..000000000 --- a/Benchmarks/IterationBenchmarks.md +++ /dev/null @@ -1,28 +0,0 @@ -## IterationBenchmarks - -### Source -[IterationBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/IterationBenchmarks.cs) - -### References: -- Linq: 4.8.4300.0 -- System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) -- System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) -- System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) - -### Results: -``` ini - -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT - -Job=.NET Core 5.0 Runtime=.NET Core 5.0 - -``` -| Method | Count | Mean | Error | StdDev | Ratio | -|------- |---------- |---------:|---------:|---------:|------:| -| LT | 100000000 | 51.32 ms | 0.108 ms | 0.096 ms | 1.00 | -| LTE | 100000000 | 51.30 ms | 0.079 ms | 0.066 ms | 1.00 | diff --git a/Benchmarks/ListIterationBenchmarks.md b/Benchmarks/ListIterationBenchmarks.md new file mode 100644 index 000000000..5e8bbd81b --- /dev/null +++ b/Benchmarks/ListIterationBenchmarks.md @@ -0,0 +1,33 @@ +## ListIterationBenchmarks + +### Source +[ListIterationBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ListIterationBenchmarks.cs) + +### References: +- Linq: 6.0.0-preview.5.21301.5 +- System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) +- System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) +- System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) + +### Results: +``` ini + +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) +Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + +Runtime=.NET 6.0 + +``` +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------- |-------------- |-------- |------------:|----------:|----------:|------------:|------:|--------:|------:|------:|------:|----------:| +| List_Enumerable | List | 1000000 | 1,406.4 μs | 27.92 μs | 57.66 μs | 1,373.8 μs | 1.00 | 0.00 | - | - | - | - | +| List_Indexer | List | 1000000 | 1,071.0 μs | 3.83 μs | 3.20 μs | 1,070.7 μs | 0.77 | 0.03 | - | - | - | 1 B | +| List_Span | List | 1000000 | 487.5 μs | 15.26 μs | 44.99 μs | 459.3 μs | 0.35 | 0.03 | - | - | - | - | +| | | | | | | | | | | | | | +| ImmutableList_Enumerable | ImmutableList | 1000000 | 35,277.5 μs | 345.09 μs | 322.79 μs | 35,354.5 μs | 1.00 | 0.00 | - | - | - | 10 B | +| ImmutableList_Indexer | ImmutableList | 1000000 | 63,181.9 μs | 315.41 μs | 295.03 μs | 63,129.3 μs | 1.79 | 0.02 | - | - | - | 55 B | diff --git a/Benchmarks/RangeBenchmarks.md b/Benchmarks/RangeBenchmarks.md index fd0b0484e..640a5a436 100644 --- a/Benchmarks/RangeBenchmarks.md +++ b/Benchmarks/RangeBenchmarks.md @@ -4,29 +4,30 @@ [RangeBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/RangeBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|---------------------- |------------ |------ |------------:|---------:|---------:|------:|-------:|------:|------:|----------:| -| Linq_Range | Range | 100 | 417.46 ns | 1.612 ns | 1.258 ns | 1.00 | 0.0191 | - | - | 40 B | -| StructLinq_Range | Range | 100 | 33.49 ns | 0.058 ns | 0.049 ns | 0.08 | - | - | - | - | -| Hyperlinq_Range | Range | 100 | 43.61 ns | 0.065 ns | 0.061 ns | 0.10 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Range_Async | Range_Async | 100 | 4,228.69 ns | 9.630 ns | 8.042 ns | 1.00 | 0.0229 | - | - | 48 B | -| Hyperlinq_Range_Async | Range_Async | 100 | 1,295.62 ns | 1.944 ns | 1.819 ns | 0.31 | 0.0153 | - | - | 32 B | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|---------------- |------------ |------ |------------:|----------:|----------:|------:|-------:|------:|------:|----------:| +| Linq | Range | 100 | 372.51 ns | 2.888 ns | 2.254 ns | 1.00 | 0.0191 | - | - | 40 B | +| StructLinq | Range | 100 | 33.64 ns | 0.143 ns | 0.112 ns | 0.09 | - | - | - | - | +| Hyperlinq | Range | 100 | 41.45 ns | 0.259 ns | 0.318 ns | 0.11 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Async | Range_Async | 100 | 3,676.68 ns | 15.301 ns | 13.564 ns | 1.00 | 0.0229 | - | - | 48 B | +| Hyperlinq_Async | Range_Async | 100 | 1,234.74 ns | 5.418 ns | 4.524 ns | 0.34 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/RangeToArrayBenchmarks.md b/Benchmarks/RangeToArrayBenchmarks.md index 0a9b07ef3..f3a177647 100644 --- a/Benchmarks/RangeToArrayBenchmarks.md +++ b/Benchmarks/RangeToArrayBenchmarks.md @@ -4,31 +4,31 @@ [RangeToArrayBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/RangeToArrayBenchmarks.cs) ### References: -- Linq: 5.0.2 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta34](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta34) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores -.NET Core SDK=5.0.200-preview.20614.14 - [Host] : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|---------------- |------------ |------ |----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| -| Linq | Range | 100 | 96.63 ns | 0.862 ns | 0.764 ns | 1.00 | 0.00 | 0.2218 | - | - | 464 B | -| StructLinq | Range | 100 | 99.00 ns | 0.820 ns | 0.640 ns | 1.03 | 0.01 | 0.2142 | - | - | 448 B | -| LinqFaster_SIMD | Range | 100 | 45.58 ns | 0.948 ns | 1.054 ns | 0.47 | 0.01 | 0.2027 | - | - | 424 B | -| Hyperlinq | Range | 100 | 62.69 ns | 0.764 ns | 0.677 ns | 0.65 | 0.01 | 0.2027 | - | - | 424 B | -| | | | | | | | | | | | | -| Linq_Async | Range_Async | 100 | 119.78 ns | 2.043 ns | 1.911 ns | 1.00 | 0.00 | 0.2255 | - | - | 472 B | -| Hyperlinq_Async | Range_Async | 100 | 122.04 ns | 0.868 ns | 0.769 ns | 1.02 | 0.02 | 0.2027 | - | - | 424 B | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Allocated | +|---------------- |------------ |------ |----------:|---------:|---------:|-------------:|--------:|-------:|----------:| +| Linq | Range | 100 | 98.10 ns | 0.503 ns | 0.393 ns | baseline | | 0.2217 | 464 B | +| StructLinq | Range | 100 | 106.79 ns | 2.013 ns | 1.785 ns | 1.09x slower | 0.02x | 0.2142 | 448 B | +| LinqFaster_SIMD | Range | 100 | 46.08 ns | 0.330 ns | 0.292 ns | 2.13x faster | 0.02x | 0.2027 | 424 B | +| Hyperlinq | Range | 100 | 52.06 ns | 0.499 ns | 0.417 ns | 1.88x faster | 0.02x | 0.2027 | 424 B | +| | | | | | | | | | | +| Linq_Async | Range_Async | 100 | 129.59 ns | 1.059 ns | 0.884 ns | baseline | | 0.2255 | 472 B | +| Hyperlinq_Async | Range_Async | 100 | 166.08 ns | 1.368 ns | 1.213 ns | 1.28x slower | 0.01x | 0.2027 | 424 B | diff --git a/Benchmarks/ReadOnlyFieldsBenchmarks.md b/Benchmarks/ReadOnlyFieldsBenchmarks.md new file mode 100644 index 000000000..daf553cd8 --- /dev/null +++ b/Benchmarks/ReadOnlyFieldsBenchmarks.md @@ -0,0 +1,30 @@ +## ReadOnlyFieldsBenchmarks + +### Source +[ReadOnlyFieldsBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ReadOnlyFieldsBenchmarks.cs) + +### References: +- Linq: 6.0.0-preview.5.21301.5 +- System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) +- System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) +- System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) + +### Results: +``` ini + +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) +Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + +Runtime=.NET 6.0 + +``` +| Method | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|---------------- |------ |---------:|--------:|--------:|------:|------:|------:|------:|----------:| +| Baseline | 1000 | 545.7 ns | 1.41 ns | 1.25 ns | 1.00 | - | - | - | - | +| ReadOnlyCurrent | 1000 | 545.6 ns | 1.20 ns | 1.12 ns | 1.00 | - | - | - | - | +| ReadOnlyField | 1000 | 545.9 ns | 1.41 ns | 1.32 ns | 1.00 | - | - | - | - | diff --git a/Benchmarks/RepeatBenchmarks.md b/Benchmarks/RepeatBenchmarks.md index 8f62e2ef5..59c8e4232 100644 --- a/Benchmarks/RepeatBenchmarks.md +++ b/Benchmarks/RepeatBenchmarks.md @@ -4,30 +4,30 @@ [RepeatBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/RepeatBenchmarks.cs) ### References: -- Linq: 5.0.2 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta34](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta34) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores -.NET Core SDK=5.0.200-preview.20614.14 - [Host] : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|---------------- |------------- |------ |------------:|----------:|----------:|------------:|------:|-------:|------:|------:|----------:| -| Linq_Count | Repeat | 100 | 578.38 ns | 32.322 ns | 95.302 ns | 623.45 ns | 1.00 | 0.0153 | - | - | 32 B | -| StructLinq | Repeat | 100 | 57.71 ns | 0.545 ns | 0.455 ns | 57.55 ns | 0.10 | - | - | - | - | -| Hyperlinq | Repeat | 100 | 41.23 ns | 0.145 ns | 0.121 ns | 41.18 ns | 0.07 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_Async | Repeat_Async | 100 | 6,120.12 ns | 93.560 ns | 87.516 ns | 6,088.82 ns | 1.00 | 0.0229 | - | - | 48 B | -| Hyperlinq_Async | Repeat_Async | 100 | 945.28 ns | 7.413 ns | 6.572 ns | 944.56 ns | 0.15 | - | - | - | - | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|---------------- |------------- |------ |------------:|----------:|----------:|------:|-------:|------:|------:|----------:| +| Linq | Repeat | 100 | 392.90 ns | 4.207 ns | 3.285 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq | Repeat | 100 | 44.30 ns | 0.150 ns | 0.133 ns | 0.11 | - | - | - | - | +| Hyperlinq | Repeat | 100 | 146.99 ns | 0.322 ns | 0.302 ns | 0.37 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Async | Repeat_Async | 100 | 4,732.19 ns | 47.740 ns | 39.865 ns | 1.00 | 0.0229 | - | - | 48 B | +| Hyperlinq_Async | Repeat_Async | 100 | 769.57 ns | 1.426 ns | 1.265 ns | 0.16 | - | - | - | - | diff --git a/Benchmarks/RepeatToArrayBenchmarks.md b/Benchmarks/RepeatToArrayBenchmarks.md index 52589e6ab..68118ad44 100644 --- a/Benchmarks/RepeatToArrayBenchmarks.md +++ b/Benchmarks/RepeatToArrayBenchmarks.md @@ -4,32 +4,32 @@ [RepeatToArrayBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/RepeatToArrayBenchmarks.cs) ### References: -- Linq: 5.0.2 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta34](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta34) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores -.NET Core SDK=5.0.200-preview.20614.14 - [Host] : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|---------------- |------------- |------ |----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| -| Linq | Repeat | 100 | 140.08 ns | 2.839 ns | 2.915 ns | 1.00 | 0.00 | 0.2179 | - | - | 456 B | -| StructLinq | Repeat | 100 | 164.29 ns | 3.302 ns | 3.391 ns | 1.17 | 0.03 | 0.2141 | - | - | 448 B | -| LinqFaster_SIMD | Repeat | 100 | 36.61 ns | 0.810 ns | 1.053 ns | 0.26 | 0.01 | 0.2027 | - | - | 424 B | -| Hyperlinq | Repeat | 100 | 63.87 ns | 1.072 ns | 1.053 ns | 0.46 | 0.01 | 0.2027 | - | - | 424 B | -| Hyperlinq_SIMD | Repeat | 100 | 52.59 ns | 0.871 ns | 0.815 ns | 0.38 | 0.01 | 0.2027 | - | - | 424 B | -| | | | | | | | | | | | | -| Linq_Async | Repeat_Async | 100 | 162.26 ns | 3.103 ns | 3.048 ns | 1.00 | 0.00 | 0.2255 | - | - | 472 B | -| Hyperlinq_Async | Repeat_Async | 100 | 178.38 ns | 1.134 ns | 0.947 ns | 1.10 | 0.02 | 0.2027 | - | - | 424 B | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Allocated | +|---------------- |------------- |------ |----------:|---------:|---------:|-------------:|--------:|-------:|----------:| +| Linq | Repeat | 100 | 48.20 ns | 0.986 ns | 1.923 ns | baseline | | 0.2180 | 456 B | +| StructLinq | Repeat | 100 | 87.02 ns | 0.783 ns | 0.694 ns | 1.72x slower | 0.06x | 0.2142 | 448 B | +| LinqFaster_SIMD | Repeat | 100 | 40.09 ns | 0.580 ns | 0.542 ns | 1.25x faster | 0.05x | 0.2027 | 424 B | +| Hyperlinq | Repeat | 100 | 42.98 ns | 0.979 ns | 1.690 ns | 1.12x faster | 0.05x | 0.2027 | 424 B | +| Hyperlinq_SIMD | Repeat | 100 | 51.60 ns | 1.154 ns | 1.830 ns | 1.07x slower | 0.03x | 0.2027 | 424 B | +| | | | | | | | | | | +| Linq_Async | Repeat_Async | 100 | 120.20 ns | 1.425 ns | 1.333 ns | baseline | | 0.2255 | 472 B | +| Hyperlinq_Async | Repeat_Async | 100 | 146.16 ns | 2.165 ns | 2.025 ns | 1.22x slower | 0.03x | 0.2027 | 424 B | diff --git a/Benchmarks/ReturnBenchmarks.md b/Benchmarks/ReturnBenchmarks.md index 142fef3ae..bcf875ded 100644 --- a/Benchmarks/ReturnBenchmarks.md +++ b/Benchmarks/ReturnBenchmarks.md @@ -4,28 +4,29 @@ [ReturnBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ReturnBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|----------------------- |------------- |----------:|----------:|----------:|------:|-------:|------:|------:|----------:| -| Linq_Return | Return | 23.610 ns | 0.0936 ns | 0.0830 ns | 1.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_Return | Return | 8.642 ns | 0.0131 ns | 0.0116 ns | 0.37 | - | - | - | - | -| | | | | | | | | | | -| Linq_Return_Async | Return_Async | 54.968 ns | 0.1565 ns | 0.1387 ns | 1.00 | 0.0229 | - | - | 48 B | -| Hyperlinq_Return_Async | Return_Async | 41.785 ns | 0.1437 ns | 0.1274 ns | 0.76 | - | - | - | - | +| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|----------------------- |------------- |----------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:| +| Linq_Return | Return | 15.438 ns | 0.2360 ns | 0.2208 ns | 1.00 | 0.00 | 0.0191 | - | - | 40 B | +| Hyperlinq_Return | Return | 8.734 ns | 0.0199 ns | 0.0177 ns | 0.57 | 0.01 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Return_Async | Return_Async | 59.871 ns | 1.1818 ns | 1.2645 ns | 1.00 | 0.00 | 0.0229 | - | - | 48 B | +| Hyperlinq_Return_Async | Return_Async | 40.616 ns | 0.1893 ns | 0.1678 ns | 0.68 | 0.02 | - | - | - | - | diff --git a/Benchmarks/SelectBenchmarks.md b/Benchmarks/SelectBenchmarks.md index 7ab7f5911..8bf271f4e 100644 --- a/Benchmarks/SelectBenchmarks.md +++ b/Benchmarks/SelectBenchmarks.md @@ -4,32 +4,62 @@ [SelectBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectBenchmarks.cs) ### References: -- Linq: 5.0.2 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta33](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta33) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores -.NET Core SDK=5.0.200-preview.20614.14 - [Host] : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 Categories=Array +Runtime=.NET 6.0 ``` -| Method | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------- |------ |---------:|--------:|--------:|------:|-------:|------:|------:|----------:| -| Linq_Array | 100 | 642.1 ns | 2.04 ns | 1.81 ns | 1.00 | 0.0229 | - | - | 48 B | -| StructLinq_Array | 100 | 228.1 ns | 0.33 ns | 0.26 ns | 0.36 | - | - | - | - | -| Hyperlinq_Span_For | 100 | 170.3 ns | 1.06 ns | 0.99 ns | 0.27 | - | - | - | - | -| Hyperlinq_Span_Foreach | 100 | 202.8 ns | 0.68 ns | 0.60 ns | 0.32 | - | - | - | - | -| Hyperlinq_Span_SIMD | 100 | 411.2 ns | 2.49 ns | 2.33 ns | 0.64 | - | - | - | - | -| Hyperlinq_Memory_For | 100 | 344.4 ns | 2.31 ns | 2.05 ns | 0.54 | - | - | - | - | -| Hyperlinq_Memory_Foreach | 100 | 231.5 ns | 1.13 ns | 0.88 ns | 0.36 | - | - | - | - | -| Hyperlinq_Memory_SIMD | 100 | 451.4 ns | 2.79 ns | 2.61 ns | 0.70 | - | - | - | - | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 634.9 ns | 6.67 ns | 5.92 ns | 1.00 | 0.0229 | - | - | 48 B | +| StructLinq_Array | Array | 100 | 206.7 ns | 1.40 ns | 1.17 ns | 0.33 | - | - | - | - | +| Hyperlinq_Array_For | Array | 100 | 300.1 ns | 2.67 ns | 2.49 ns | 0.47 | - | - | - | - | +| Hyperlinq_Array_Foreach | Array | 100 | 209.7 ns | 0.70 ns | 0.62 ns | 0.33 | - | - | - | - | +| Hyperlinq_Span_For | Array | 100 | 196.8 ns | 1.09 ns | 1.02 ns | 0.31 | - | - | - | - | +| Hyperlinq_Span_Foreach | Array | 100 | 230.9 ns | 0.87 ns | 0.81 ns | 0.36 | - | - | - | - | +| Hyperlinq_Memory_For | Array | 100 | 350.3 ns | 2.06 ns | 1.72 ns | 0.55 | - | - | - | - | +| Hyperlinq_Memory_Foreach | Array | 100 | 232.6 ns | 0.50 ns | 0.41 ns | 0.37 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,168.6 ns | 4.90 ns | 3.83 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 789.1 ns | 2.65 ns | 2.35 ns | 0.67 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 209.2 ns | 0.60 ns | 0.53 ns | 0.18 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 1,192.1 ns | 5.24 ns | 4.38 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 780.3 ns | 3.58 ns | 3.18 ns | 0.65 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 208.0 ns | 0.74 ns | 0.62 ns | 0.17 | - | - | - | - | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 1,190.9 ns | 11.63 ns | 10.31 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_List_Value | List_Value | 100 | 440.0 ns | 1.36 ns | 1.27 ns | 0.37 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 743.3 ns | 5.20 ns | 4.61 ns | 0.62 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 6,530.2 ns | 23.55 ns | 20.88 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 4,789.9 ns | 24.40 ns | 22.82 ns | 0.73 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 1,157.4 ns | 6.61 ns | 6.19 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 789.6 ns | 5.00 ns | 4.44 ns | 0.68 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 758.0 ns | 4.30 ns | 3.81 ns | 0.66 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 1,158.5 ns | 4.83 ns | 3.77 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 789.2 ns | 4.96 ns | 4.40 ns | 0.68 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 761.8 ns | 3.01 ns | 2.81 ns | 0.66 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 1,178.0 ns | 8.81 ns | 8.24 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_List_Reference | List_Reference | 100 | 778.2 ns | 2.60 ns | 2.43 ns | 0.66 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 782.6 ns | 3.64 ns | 3.04 ns | 0.66 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 6,551.7 ns | 31.19 ns | 29.17 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 5,147.7 ns | 14.49 ns | 12.85 ns | 0.79 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/SelectCountBenchmarks.md b/Benchmarks/SelectCountBenchmarks.md index 520b12d00..93d15f732 100644 --- a/Benchmarks/SelectCountBenchmarks.md +++ b/Benchmarks/SelectCountBenchmarks.md @@ -4,58 +4,57 @@ [SelectCountBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectCountBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` | Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | |------------------------------------ |-------------------------- |------ |-------------:|-----------:|-----------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 219.134 ns | 0.8228 ns | 0.6870 ns | 1.00 | 0.00 | 0.0229 | - | - | 48 B | -| StructLinq_Array | Array | 100 | 10.007 ns | 0.0146 ns | 0.0130 ns | 0.05 | 0.00 | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 8.946 ns | 0.0141 ns | 0.0125 ns | 0.04 | 0.00 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 8.940 ns | 0.0145 ns | 0.0135 ns | 0.04 | 0.00 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 9.489 ns | 0.0204 ns | 0.0170 ns | 0.04 | 0.00 | - | - | - | - | +| Linq_Array | Array | 100 | 196.867 ns | 1.2466 ns | 1.1051 ns | 1.00 | 0.00 | 0.0229 | - | - | 48 B | +| StructLinq_Array | Array | 100 | 10.218 ns | 0.0308 ns | 0.0273 ns | 0.05 | 0.00 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 15.495 ns | 0.0355 ns | 0.0314 ns | 0.08 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 803.504 ns | 3.4588 ns | 3.0661 ns | 1.00 | 0.00 | 0.0420 | - | - | 88 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 796.036 ns | 1.6843 ns | 1.4065 ns | 0.99 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 149.788 ns | 0.2333 ns | 0.2068 ns | 0.19 | 0.00 | - | - | - | - | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 817.248 ns | 4.7910 ns | 4.0007 ns | 1.00 | 0.00 | 0.0420 | - | - | 88 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 763.890 ns | 5.3349 ns | 4.7292 ns | 0.94 | 0.01 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 146.331 ns | 0.3951 ns | 0.3696 ns | 0.18 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 805.356 ns | 2.4730 ns | 2.3133 ns | 1.00 | 0.00 | 0.0420 | - | - | 88 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 774.031 ns | 1.2887 ns | 1.0761 ns | 0.96 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 11.941 ns | 0.0139 ns | 0.0123 ns | 0.01 | 0.00 | - | - | - | - | +| Linq_Collection_Value | Collection_Value | 100 | 809.252 ns | 4.1536 ns | 3.6821 ns | 1.00 | 0.00 | 0.0420 | - | - | 88 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 736.884 ns | 1.7281 ns | 1.6165 ns | 0.91 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 16.493 ns | 0.0749 ns | 0.0625 ns | 0.02 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 379.943 ns | 0.8789 ns | 0.7791 ns | 1.00 | 0.00 | 0.0267 | - | - | 56 B | -| StructLinq_List_Value | List_Value | 100 | 10.201 ns | 0.0244 ns | 0.0229 ns | 0.03 | 0.00 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 7.511 ns | 0.0271 ns | 0.0254 ns | 0.02 | 0.00 | - | - | - | - | +| Linq_List_Value | List_Value | 100 | 439.698 ns | 2.2291 ns | 2.0851 ns | 1.00 | 0.00 | 0.0267 | - | - | 56 B | +| StructLinq_List_Value | List_Value | 100 | 10.504 ns | 0.0398 ns | 0.0372 ns | 0.02 | 0.00 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 4.450 ns | 0.0275 ns | 0.0244 ns | 0.01 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 8,902.444 ns | 23.6333 ns | 19.7349 ns | 1.00 | 0.00 | 0.0458 | - | - | 104 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 8,968.740 ns | 17.1138 ns | 14.2908 ns | 1.01 | 0.00 | 0.0610 | - | - | 136 B | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 7,285.015 ns | 19.6921 ns | 17.4565 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 790.400 ns | 2.4782 ns | 2.1968 ns | 0.11 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 594.794 ns | 0.9684 ns | 0.8585 ns | 1.00 | 0.00 | 0.0420 | - | - | 88 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 566.260 ns | 0.9518 ns | 0.8903 ns | 0.95 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 258.161 ns | 0.8138 ns | 0.7613 ns | 0.43 | 0.00 | 0.0153 | - | - | 32 B | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 809.637 ns | 4.1360 ns | 3.8688 ns | 1.00 | 0.00 | 0.0420 | - | - | 88 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 761.509 ns | 3.4922 ns | 3.2666 ns | 0.94 | 0.01 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 397.099 ns | 1.3983 ns | 1.2395 ns | 0.49 | 0.00 | 0.0153 | - | - | 32 B | | | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 597.569 ns | 3.9864 ns | 3.5338 ns | 1.000 | 0.00 | 0.0420 | - | - | 88 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 572.285 ns | 1.3061 ns | 1.2217 ns | 0.958 | 0.01 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 4.136 ns | 0.0051 ns | 0.0043 ns | 0.007 | 0.00 | - | - | - | - | +| Linq_Collection_Reference | Collection_Reference | 100 | 809.793 ns | 6.4629 ns | 5.3968 ns | 1.000 | 0.00 | 0.0420 | - | - | 88 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 738.381 ns | 2.5787 ns | 2.1533 ns | 0.912 | 0.01 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 4.726 ns | 0.0338 ns | 0.0299 ns | 0.006 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 360.074 ns | 1.2968 ns | 1.1495 ns | 1.00 | 0.00 | 0.0267 | - | - | 56 B | -| StructLinq_List_Reference | List_Reference | 100 | 526.575 ns | 7.2842 ns | 8.0964 ns | 1.47 | 0.02 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 7.479 ns | 0.0248 ns | 0.0207 ns | 0.02 | 0.00 | - | - | - | - | +| Linq_List_Reference | List_Reference | 100 | 430.338 ns | 4.9343 ns | 4.1204 ns | 1.00 | 0.00 | 0.0267 | - | - | 56 B | +| StructLinq_List_Reference | List_Reference | 100 | 765.248 ns | 5.5823 ns | 4.9486 ns | 1.78 | 0.03 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 4.693 ns | 0.0246 ns | 0.0230 ns | 0.01 | 0.00 | - | - | - | - | | | | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 8,636.721 ns | 29.1881 ns | 24.3733 ns | 1.00 | 0.00 | 0.0458 | - | - | 104 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 8,940.788 ns | 23.7462 ns | 22.2122 ns | 1.04 | 0.00 | 0.0610 | - | - | 152 B | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 6,910.703 ns | 32.3418 ns | 30.2525 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,432.868 ns | 2.7418 ns | 2.5647 ns | 0.21 | 0.00 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/SelectManyBenchmarks.md b/Benchmarks/SelectManyBenchmarks.md index f7e46be29..affe992dc 100644 --- a/Benchmarks/SelectManyBenchmarks.md +++ b/Benchmarks/SelectManyBenchmarks.md @@ -4,48 +4,49 @@ [SelectManyBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectManyBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------- |-------------------------- |------ |----------:|----------:|----------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 3.416 μs | 0.0082 μs | 0.0073 μs | 1.00 | 1.9569 | - | - | 4096 B | -| Hyperlinq_Array | Array | 100 | 1.270 μs | 0.0012 μs | 0.0010 μs | 0.37 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 1.361 μs | 0.0021 μs | 0.0019 μs | 0.40 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 3.631 μs | 0.0080 μs | 0.0067 μs | 1.00 | 1.9569 | - | - | 4096 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 3.505 μs | 0.0063 μs | 0.0053 μs | 0.97 | 2.3537 | - | - | 4928 B | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 3.730 μs | 0.0086 μs | 0.0080 μs | 1.00 | 1.9569 | - | - | 4096 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 3.454 μs | 0.0116 μs | 0.0103 μs | 0.93 | 2.3537 | - | - | 4928 B | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 3.725 μs | 0.0064 μs | 0.0054 μs | 1.00 | 1.9569 | - | - | 4096 B | -| Hyperlinq_List_Value | List_Value | 100 | 1.331 μs | 0.0021 μs | 0.0016 μs | 0.36 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 13.882 μs | 0.0308 μs | 0.0273 μs | 1.00 | 2.3804 | - | - | 4984 B | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 3.428 μs | 0.0070 μs | 0.0062 μs | 1.00 | 1.9569 | - | - | 4096 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 1.497 μs | 0.0029 μs | 0.0026 μs | 0.44 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 3.426 μs | 0.0069 μs | 0.0058 μs | 1.00 | 1.9569 | - | - | 4096 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 1.487 μs | 0.0019 μs | 0.0017 μs | 0.43 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 3.430 μs | 0.0068 μs | 0.0061 μs | 1.00 | 1.9569 | - | - | 4096 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 1.327 μs | 0.0017 μs | 0.0016 μs | 0.39 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 13.511 μs | 0.0257 μs | 0.0215 μs | 1.00 | 2.3804 | - | - | 4984 B | +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------- |-------------------------- |------ |----------:|----------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 2.756 μs | 0.0184 μs | 0.0163 μs | 2.753 μs | 1.00 | 0.00 | 1.9569 | - | - | 4,096 B | +| Hyperlinq_Array | Array | 100 | 1.225 μs | 0.0035 μs | 0.0033 μs | 1.224 μs | 0.44 | 0.00 | - | - | - | - | +| Hyperlinq_Memory | Array | 100 | 1.381 μs | 0.0050 μs | 0.0042 μs | 1.380 μs | 0.50 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 2.968 μs | 0.0281 μs | 0.0262 μs | 2.964 μs | 1.00 | 0.00 | 1.9569 | - | - | 4,096 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 3.670 μs | 0.0176 μs | 0.0147 μs | 3.668 μs | 1.24 | 0.01 | 2.3575 | - | - | 4,936 B | +| | | | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 3.216 μs | 0.0163 μs | 0.0144 μs | 3.217 μs | 1.00 | 0.00 | 1.9569 | - | - | 4,096 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 3.312 μs | 0.0209 μs | 0.0185 μs | 3.308 μs | 1.03 | 0.01 | 2.3575 | - | - | 4,936 B | +| | | | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 2.993 μs | 0.0211 μs | 0.0187 μs | 2.989 μs | 1.00 | 0.00 | 1.9569 | - | - | 4,096 B | +| Hyperlinq_List_Value | List_Value | 100 | 3.341 μs | 0.0109 μs | 0.0091 μs | 3.343 μs | 1.12 | 0.01 | 2.3499 | - | - | 4,920 B | +| | | | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 11.621 μs | 0.0627 μs | 0.0587 μs | 11.609 μs | 1.00 | 0.00 | 2.3346 | - | - | 4,904 B | +| | | | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 3.008 μs | 0.0336 μs | 0.0298 μs | 2.996 μs | 1.00 | 0.00 | 1.9569 | - | - | 4,096 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 3.409 μs | 0.0669 μs | 0.1322 μs | 3.331 μs | 1.19 | 0.04 | 2.3499 | - | - | 4,920 B | +| | | | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 3.076 μs | 0.0604 μs | 0.1120 μs | 3.004 μs | 1.00 | 0.00 | 1.9569 | - | - | 4,096 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 3.482 μs | 0.0154 μs | 0.0206 μs | 3.476 μs | 1.11 | 0.04 | 2.3499 | - | - | 4,920 B | +| | | | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 3.222 μs | 0.0175 μs | 0.0163 μs | 3.216 μs | 1.00 | 0.00 | 1.9569 | - | - | 4,096 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 3.599 μs | 0.0149 μs | 0.0140 μs | 3.599 μs | 1.12 | 0.01 | 2.3499 | - | - | 4,920 B | +| | | | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 11.918 μs | 0.0477 μs | 0.0423 μs | 11.915 μs | 1.00 | 0.00 | 2.3346 | - | - | 4,904 B | diff --git a/Benchmarks/SelectSumBenchmarks.md b/Benchmarks/SelectSumBenchmarks.md index 2bae871ac..6df38da3a 100644 --- a/Benchmarks/SelectSumBenchmarks.md +++ b/Benchmarks/SelectSumBenchmarks.md @@ -4,29 +4,58 @@ [SelectSumBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectSumBenchmarks.cs) ### References: -- Linq: 5.0.2 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta34](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta34) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores -.NET Core SDK=5.0.200-preview.20614.14 - [Host] : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 Categories=Array +Runtime=.NET 6.0 ``` -| Method | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|-------------------- |------ |----------:|---------:|---------:|------:|-------:|------:|------:|----------:| -| Linq_Array | 100 | 667.37 ns | 6.329 ns | 7.773 ns | 1.00 | 0.0229 | - | - | 48 B | -| StructLinq_Array | 100 | 187.38 ns | 0.992 ns | 0.828 ns | 0.28 | - | - | - | - | -| Hyperlinq_Array | 100 | 173.83 ns | 2.209 ns | 1.845 ns | 0.26 | - | - | - | - | -| Hyperlinq_Span | 100 | 170.41 ns | 0.836 ns | 0.698 ns | 0.25 | - | - | - | - | -| Hyperlinq_Span_SIMD | 100 | 63.81 ns | 1.143 ns | 1.013 ns | 0.10 | - | - | - | - | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |------------:|----------:|----------:|------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 649.45 ns | 5.100 ns | 4.770 ns | 1.00 | 0.0229 | - | - | 48 B | +| StructLinq_Array | Array | 100 | 215.68 ns | 0.939 ns | 0.784 ns | 0.33 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 222.11 ns | 0.351 ns | 0.311 ns | 0.34 | - | - | - | - | +| Hyperlinq_Array_SIMD | Array | 100 | 64.66 ns | 0.289 ns | 0.271 ns | 0.10 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,153.23 ns | 5.437 ns | 4.820 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 760.14 ns | 6.392 ns | 5.666 ns | 0.66 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 203.58 ns | 0.543 ns | 0.454 ns | 0.18 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 1,188.28 ns | 11.234 ns | 10.509 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 733.31 ns | 3.357 ns | 3.140 ns | 0.62 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 210.94 ns | 1.034 ns | 0.807 ns | 0.18 | - | - | - | - | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 1,170.55 ns | 10.191 ns | 7.957 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_List_Value | List_Value | 100 | 392.49 ns | 1.152 ns | 1.021 ns | 0.34 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 767.69 ns | 2.820 ns | 2.638 ns | 0.66 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 6,939.54 ns | 31.039 ns | 27.515 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,004.69 ns | 7.381 ns | 6.543 ns | 0.29 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 1,201.44 ns | 6.594 ns | 5.845 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 762.89 ns | 3.737 ns | 3.312 ns | 0.63 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 788.19 ns | 4.610 ns | 4.312 ns | 0.66 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 1,201.80 ns | 6.314 ns | 5.906 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 733.73 ns | 4.762 ns | 4.221 ns | 0.61 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 792.80 ns | 3.573 ns | 3.167 ns | 0.66 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 1,225.54 ns | 14.180 ns | 12.571 ns | 1.00 | 0.0420 | - | - | 88 B | +| StructLinq_List_Reference | List_Reference | 100 | 758.23 ns | 4.108 ns | 3.207 ns | 0.62 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 771.48 ns | 4.268 ns | 3.784 ns | 0.63 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 6,894.63 ns | 27.438 ns | 24.323 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,798.15 ns | 4.396 ns | 3.897 ns | 0.41 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/SelectToArrayBenchmarks.md b/Benchmarks/SelectToArrayBenchmarks.md index a3b139a00..d78393d54 100644 --- a/Benchmarks/SelectToArrayBenchmarks.md +++ b/Benchmarks/SelectToArrayBenchmarks.md @@ -4,61 +4,59 @@ [SelectToArrayBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToArrayBenchmarks.cs) ### References: -- Linq: 5.0.3 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta39](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta39) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores -.NET Core SDK=6.0.100-preview.1.21103.13 - [Host] : .NET Core 5.0.3 (CoreCLR 5.0.321.7212, CoreFX 5.0.321.7212), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.3 (CoreCLR 5.0.321.7212, CoreFX 5.0.321.7212), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |------------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 267.88 ns | 2.668 ns | 2.365 ns | 1.00 | 0.00 | 0.2255 | - | - | 472 B | -| StructLinq_Array | Array | 100 | 273.06 ns | 4.607 ns | 4.084 ns | 1.02 | 0.01 | 0.2027 | - | - | 424 B | -| LinqFasterSIMD_Array | Array | 100 | 99.65 ns | 1.953 ns | 1.827 ns | 0.37 | 0.01 | 0.2027 | - | - | 424 B | -| Hyperlinq_Array | Array | 100 | 269.94 ns | 4.902 ns | 4.585 ns | 1.01 | 0.02 | 0.2027 | - | - | 424 B | -| Hyperlinq_Span | Array | 100 | 239.28 ns | 2.553 ns | 2.388 ns | 0.89 | 0.01 | 0.2027 | - | - | 424 B | -| Hyperlinq_Span_SIMD | Array | 100 | 109.47 ns | 1.910 ns | 1.693 ns | 0.41 | 0.01 | 0.2027 | - | - | 424 B | -| Hyperlinq_Memory | Array | 100 | 274.17 ns | 5.390 ns | 5.991 ns | 1.02 | 0.02 | 0.2027 | - | - | 424 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,285.51 ns | 25.581 ns | 26.270 ns | 1.00 | 0.00 | 0.5913 | - | - | 1240 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,129.23 ns | 8.712 ns | 7.723 ns | 0.88 | 0.02 | 0.2174 | - | - | 456 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 663.26 ns | 6.979 ns | 6.528 ns | 0.52 | 0.01 | 0.2022 | - | - | 424 B | -| Hyperlinq_Enumerable_Value_SIMD | Enumerable_Value | 100 | 700.52 ns | 9.899 ns | 10.591 ns | 0.55 | 0.01 | 0.2289 | - | - | 480 B | -| | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 1,273.49 ns | 18.642 ns | 16.526 ns | 1.00 | 0.00 | 0.5913 | - | - | 1240 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 1,153.21 ns | 6.918 ns | 6.133 ns | 0.91 | 0.01 | 0.2174 | - | - | 456 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 406.46 ns | 6.649 ns | 6.219 ns | 0.32 | 0.01 | 0.2027 | - | - | 424 B | -| | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 468.99 ns | 4.210 ns | 3.516 ns | 1.00 | 0.00 | 0.2294 | - | - | 480 B | -| StructLinq_List_Value | List_Value | 100 | 445.91 ns | 5.327 ns | 4.159 ns | 0.95 | 0.01 | 0.2027 | - | - | 424 B | -| Hyperlinq_List_Value | List_Value | 100 | 511.99 ns | 5.562 ns | 4.931 ns | 1.09 | 0.01 | 0.2027 | - | - | 424 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 964.21 ns | 17.884 ns | 15.854 ns | 1.00 | 0.00 | 0.5922 | - | - | 1240 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 936.40 ns | 10.404 ns | 8.688 ns | 0.97 | 0.02 | 0.2174 | - | - | 456 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 1,000.13 ns | 5.117 ns | 4.273 ns | 1.04 | 0.02 | 0.2174 | - | - | 456 B | -| Hyperlinq_Enumerable_Reference_SIMD | Enumerable_Reference | 100 | 978.08 ns | 6.965 ns | 6.515 ns | 1.02 | 0.02 | 0.2441 | - | - | 512 B | -| | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 958.07 ns | 11.892 ns | 9.930 ns | 1.00 | 0.00 | 0.5922 | - | - | 1240 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 938.89 ns | 9.194 ns | 7.178 ns | 0.98 | 0.01 | 0.2174 | - | - | 456 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 645.53 ns | 8.129 ns | 7.604 ns | 0.67 | 0.01 | 0.2174 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 470.57 ns | 6.943 ns | 6.155 ns | 1.00 | 0.00 | 0.2294 | - | - | 480 B | -| StructLinq_List_Reference | List_Reference | 100 | 942.82 ns | 5.208 ns | 4.066 ns | 2.01 | 0.02 | 0.2174 | - | - | 456 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 483.23 ns | 3.540 ns | 3.312 ns | 1.03 | 0.01 | 0.2027 | - | - | 424 B | -| | | | | | | | | | | | | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 9,811.24 ns | 52.535 ns | 49.142 ns | ? | ? | 0.8087 | - | - | 1712 B | -| | | | | | | | | | | | | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 9,564.61 ns | 61.404 ns | 57.437 ns | ? | ? | 0.8240 | - | - | 1728 B | +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Allocated | +|------------------------------------ |-------------------------- |------ |------------:|-----------:|-----------:|------------:|-------------:|--------:|-------:|----------:| +| Linq_Array | Array | 100 | 473.47 ns | 8.574 ns | 13.093 ns | 474.67 ns | baseline | | 0.2251 | 472 B | +| StructLinq_Array | Array | 100 | 279.61 ns | 4.617 ns | 4.093 ns | 282.23 ns | 1.72x faster | 0.04x | 0.2027 | 424 B | +| LinqFasterSIMD_Array | Array | 100 | 85.80 ns | 1.640 ns | 2.455 ns | 85.24 ns | 5.53x faster | 0.21x | 0.2027 | 424 B | +| Hyperlinq_Array | Array | 100 | 280.63 ns | 5.198 ns | 7.115 ns | 277.93 ns | 1.70x faster | 0.05x | 0.2027 | 424 B | +| Hyperlinq_Array_SIMD | Array | 100 | 102.08 ns | 1.429 ns | 1.336 ns | 102.36 ns | 4.70x faster | 0.09x | 0.2027 | 424 B | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,201.02 ns | 102.339 ns | 298.527 ns | 1,025.14 ns | baseline | | 0.5913 | 1,240 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 805.17 ns | 3.606 ns | 3.011 ns | 804.47 ns | 1.52x faster | 0.38x | 0.2174 | 456 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 715.93 ns | 14.451 ns | 14.840 ns | 711.77 ns | 1.63x faster | 0.42x | 0.2022 | 424 B | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 1,183.52 ns | 77.980 ns | 229.924 ns | 1,133.48 ns | baseline | | 0.5913 | 1,240 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 805.63 ns | 3.765 ns | 3.522 ns | 804.45 ns | 1.39x faster | 0.27x | 0.2174 | 456 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 289.68 ns | 1.739 ns | 1.542 ns | 289.81 ns | 3.86x faster | 0.78x | 0.2027 | 424 B | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 394.66 ns | 27.126 ns | 75.166 ns | 353.41 ns | baseline | | 0.2289 | 480 B | +| StructLinq_List_Value | List_Value | 100 | 403.84 ns | 8.158 ns | 7.631 ns | 404.80 ns | 1.21x faster | 0.06x | 0.2027 | 424 B | +| Hyperlinq_List_Value | List_Value | 100 | 524.14 ns | 10.475 ns | 11.643 ns | 524.80 ns | 1.09x slower | 0.07x | 0.2174 | 456 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 8,846.07 ns | 165.241 ns | 176.806 ns | 8,888.90 ns | baseline | | 0.7935 | 1,672 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 3,086.01 ns | 8.120 ns | 7.198 ns | 3,083.77 ns | 2.87x faster | 0.06x | 0.5646 | 1,184 B | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 702.52 ns | 14.093 ns | 18.814 ns | 695.92 ns | baseline | | 0.5922 | 1,240 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 805.96 ns | 12.195 ns | 12.523 ns | 802.69 ns | 1.15x slower | 0.03x | 0.2174 | 456 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 872.85 ns | 14.855 ns | 13.895 ns | 871.81 ns | 1.25x slower | 0.04x | 0.2174 | 456 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 692.92 ns | 13.428 ns | 17.925 ns | 690.88 ns | baseline | | 0.5922 | 1,240 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 804.78 ns | 2.292 ns | 2.032 ns | 804.27 ns | 1.16x slower | 0.04x | 0.2174 | 456 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 439.96 ns | 7.570 ns | 7.081 ns | 442.66 ns | 1.57x faster | 0.05x | 0.2179 | 456 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 336.83 ns | 1.248 ns | 1.106 ns | 336.54 ns | baseline | | 0.2294 | 480 B | +| StructLinq_List_Reference | List_Reference | 100 | 870.21 ns | 30.533 ns | 89.066 ns | 817.73 ns | 3.07x slower | 0.10x | 0.2174 | 456 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 523.11 ns | 10.507 ns | 12.904 ns | 520.44 ns | 1.56x slower | 0.04x | 0.2174 | 456 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 8,857.84 ns | 146.367 ns | 136.912 ns | 8,931.34 ns | baseline | | 0.7935 | 1,672 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 3,237.06 ns | 56.426 ns | 50.020 ns | 3,214.50 ns | 2.73x faster | 0.07x | 0.5798 | 1,216 B | diff --git a/Benchmarks/SelectToListBenchmarks.md b/Benchmarks/SelectToListBenchmarks.md index ebc17ede4..a74b7e096 100644 --- a/Benchmarks/SelectToListBenchmarks.md +++ b/Benchmarks/SelectToListBenchmarks.md @@ -4,56 +4,58 @@ [SelectToListBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToListBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_List | Array | 100 | 313.9 ns | 0.99 ns | 0.87 ns | 1.00 | 0.00 | 0.2408 | - | - | 504 B | -| StructLinq_List | Array | 100 | 259.8 ns | 0.65 ns | 0.61 ns | 0.83 | 0.00 | 0.2179 | - | - | 456 B | -| Hyperlinq_List | Array | 100 | 222.9 ns | 0.43 ns | 0.36 ns | 0.71 | 0.00 | 0.2179 | - | - | 456 B | -| Hyperlinq_Span | Array | 100 | 221.4 ns | 0.86 ns | 0.77 ns | 0.71 | 0.00 | 0.2179 | - | - | 456 B | -| Hyperlinq_Memory | Array | 100 | 202.7 ns | 0.68 ns | 0.57 ns | 0.65 | 0.00 | 0.2179 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,079.1 ns | 2.63 ns | 2.46 ns | 1.00 | 0.00 | 0.6065 | - | - | 1272 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,032.1 ns | 3.91 ns | 3.47 ns | 0.96 | 0.00 | 0.2327 | - | - | 488 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 617.7 ns | 0.95 ns | 0.88 ns | 0.57 | 0.00 | 0.2174 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 1,117.5 ns | 3.96 ns | 3.31 ns | 1.00 | 0.00 | 0.6065 | - | - | 1272 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 1,029.1 ns | 3.21 ns | 3.00 ns | 0.92 | 0.00 | 0.2327 | - | - | 488 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 252.1 ns | 1.15 ns | 1.08 ns | 0.23 | 0.00 | 0.2179 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 504.9 ns | 1.24 ns | 1.03 ns | 1.00 | 0.00 | 0.2441 | - | - | 512 B | -| StructLinq_List_Value | List_Value | 100 | 442.3 ns | 0.88 ns | 0.78 ns | 0.88 | 0.00 | 0.2179 | - | - | 456 B | -| Hyperlinq_List_Value | List_Value | 100 | 385.6 ns | 1.02 ns | 0.91 ns | 0.76 | 0.00 | 0.2179 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 883.2 ns | 2.55 ns | 2.26 ns | 1.00 | 0.00 | 0.6075 | - | - | 1272 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 872.5 ns | 1.61 ns | 1.43 ns | 0.99 | 0.00 | 0.2327 | - | - | 488 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 953.2 ns | 1.67 ns | 1.39 ns | 1.08 | 0.00 | 0.2327 | - | - | 488 B | -| | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 919.5 ns | 1.37 ns | 1.07 ns | 1.00 | 0.00 | 0.6075 | - | - | 1272 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 857.0 ns | 1.77 ns | 1.65 ns | 0.93 | 0.00 | 0.2327 | - | - | 488 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 604.9 ns | 4.90 ns | 4.34 ns | 0.66 | 0.01 | 0.2327 | - | - | 488 B | -| | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 458.1 ns | 1.16 ns | 1.03 ns | 1.00 | 0.00 | 0.2446 | - | - | 512 B | -| StructLinq_List_Reference | List_Reference | 100 | 875.1 ns | 1.77 ns | 1.48 ns | 1.91 | 0.00 | 0.2327 | - | - | 488 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 389.0 ns | 1.96 ns | 1.64 ns | 0.85 | 0.00 | 0.2179 | - | - | 456 B | -| | | | | | | | | | | | | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 9,480.1 ns | 14.18 ns | 12.57 ns | ? | ? | 0.6256 | - | - | 1320 B | -| | | | | | | | | | | | | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 9,036.1 ns | 22.12 ns | 19.61 ns | ? | ? | 0.6256 | - | - | 1336 B | +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Allocated | +|------------------------------------ |-------------------------- |------ |------------:|----------:|------------:|------------:|-------------:|--------:|-------:|----------:| +| Linq_Array | Array | 100 | 499.4 ns | 42.91 ns | 126.52 ns | 424.5 ns | baseline | | 0.2403 | 504 B | +| StructLinq_Array | Array | 100 | 447.4 ns | 37.68 ns | 111.09 ns | 375.6 ns | 1.16x faster | 0.32x | 0.2179 | 456 B | +| Hyperlinq_Array | Array | 100 | 395.9 ns | 27.26 ns | 80.39 ns | 353.2 ns | 1.31x faster | 0.42x | 0.2179 | 456 B | +| Hyperlinq_Array_SIMD | Array | 100 | 152.7 ns | 11.64 ns | 34.13 ns | 131.7 ns | 3.47x faster | 1.26x | 0.2179 | 456 B | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 963.8 ns | 83.58 ns | 246.45 ns | 827.4 ns | baseline | | 0.6075 | 1,272 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 838.4 ns | 9.00 ns | 7.03 ns | 836.9 ns | 1.05x faster | 0.26x | 0.2327 | 488 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 977.0 ns | 75.52 ns | 222.68 ns | 837.1 ns | 1.09x slower | 0.39x | 0.2174 | 456 B | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 884.4 ns | 63.72 ns | 186.87 ns | 770.8 ns | baseline | | 0.6075 | 1,272 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 1,093.3 ns | 87.91 ns | 259.22 ns | 1,007.2 ns | 1.29x slower | 0.42x | 0.2327 | 488 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 347.6 ns | 6.99 ns | 6.86 ns | 347.5 ns | 2.48x faster | 0.47x | 0.2179 | 456 B | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 595.9 ns | 49.90 ns | 147.13 ns | 544.4 ns | baseline | | 0.2446 | 512 B | +| StructLinq_List_Value | List_Value | 100 | 566.4 ns | 41.64 ns | 122.78 ns | 485.8 ns | 1.01x slower | 0.35x | 0.2174 | 456 B | +| Hyperlinq_List_Value | List_Value | 100 | 703.2 ns | 60.70 ns | 178.02 ns | 592.7 ns | 1.24x slower | 0.41x | 0.2327 | 488 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 11,551.1 ns | 633.63 ns | 1,868.27 ns | 11,329.3 ns | baseline | | 0.6104 | 1,280 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 4,334.4 ns | 252.18 ns | 743.57 ns | 4,145.6 ns | 2.72x faster | 0.54x | 0.5798 | 1,216 B | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 901.0 ns | 64.70 ns | 190.76 ns | 782.3 ns | baseline | | 0.6075 | 1,272 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 994.9 ns | 62.26 ns | 183.58 ns | 877.2 ns | 1.15x slower | 0.31x | 0.2327 | 488 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 1,237.7 ns | 104.77 ns | 307.28 ns | 1,124.8 ns | 1.43x slower | 0.46x | 0.2327 | 488 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 736.4 ns | 9.91 ns | 9.74 ns | 733.0 ns | baseline | | 0.6065 | 1,272 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 856.6 ns | 17.26 ns | 21.19 ns | 852.4 ns | 1.16x slower | 0.04x | 0.2327 | 488 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 631.3 ns | 54.20 ns | 159.81 ns | 524.5 ns | 1.18x faster | 0.34x | 0.2327 | 488 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 573.6 ns | 45.82 ns | 135.10 ns | 510.4 ns | baseline | | 0.2441 | 512 B | +| StructLinq_List_Reference | List_Reference | 100 | 1,082.1 ns | 87.71 ns | 258.61 ns | 972.5 ns | 2.00x slower | 0.69x | 0.2327 | 488 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 724.9 ns | 66.44 ns | 195.91 ns | 606.8 ns | 1.30x slower | 0.34x | 0.2327 | 488 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 11,006.0 ns | 599.34 ns | 1,748.30 ns | 10,037.5 ns | baseline | | 0.6104 | 1,280 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 3,231.7 ns | 10.46 ns | 8.73 ns | 3,229.7 ns | 3.40x faster | 0.33x | 0.5951 | 1,248 B | diff --git a/Benchmarks/SingleBenchmarks.md b/Benchmarks/SingleBenchmarks.md index cb629839e..b11f4ae92 100644 --- a/Benchmarks/SingleBenchmarks.md +++ b/Benchmarks/SingleBenchmarks.md @@ -4,55 +4,48 @@ [SingleBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/SingleBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |----------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 1 | 11.192 ns | 0.0386 ns | 0.0322 ns | 1.00 | 0.00 | - | - | - | - | -| Hyperlinq_Array | Array | 1 | 5.163 ns | 0.0090 ns | 0.0084 ns | 0.46 | 0.00 | - | - | - | - | -| Hyperlinq_Span | Array | 1 | 5.743 ns | 0.0095 ns | 0.0085 ns | 0.51 | 0.00 | - | - | - | - | -| Hyperlinq_Memory | Array | 1 | 7.674 ns | 0.0115 ns | 0.0096 ns | 0.69 | 0.00 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 1 | 22.396 ns | 0.0761 ns | 0.0635 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 1 | 15.166 ns | 0.0283 ns | 0.0236 ns | 0.68 | 0.00 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 1 | 22.736 ns | 0.0904 ns | 0.0845 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 1 | 22.084 ns | 0.0493 ns | 0.0437 ns | 0.97 | 0.00 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_List_Value | List_Value | 1 | 7.208 ns | 0.0328 ns | 0.0291 ns | 1.00 | 0.00 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 1 | 7.339 ns | 0.0142 ns | 0.0133 ns | 1.02 | 0.00 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 1 | 86.784 ns | 0.1634 ns | 0.1448 ns | 1.00 | 0.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 1 | NA | NA | NA | ? | ? | - | - | - | - | -| | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 1 | 18.076 ns | 0.1049 ns | 0.0930 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 1 | 19.090 ns | 0.0687 ns | 0.0643 ns | 1.06 | 0.01 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 1 | 18.010 ns | 0.1005 ns | 0.0891 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 1 | 19.315 ns | 0.0738 ns | 0.0654 ns | 1.07 | 0.01 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 1 | 7.222 ns | 0.0207 ns | 0.0183 ns | 1.00 | 0.00 | - | - | - | - | -| Hyperlinq_List_Reference | List_Reference | 1 | 7.424 ns | 0.0126 ns | 0.0099 ns | 1.03 | 0.00 | - | - | - | - | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 1 | 85.182 ns | 0.0826 ns | 0.0772 ns | 1.00 | 0.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 1 | NA | NA | NA | ? | ? | - | - | - | - | - -Benchmarks with issues: - SingleBenchmarks.Hyperlinq_AsyncEnumerable_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=1] - SingleBenchmarks.Hyperlinq_AsyncEnumerable_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=1] +| Method | Categories | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------- |-------------------------- |----------:|----------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 12.526 ns | 0.0206 ns | 0.0172 ns | 12.529 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_Array | Array | 14.608 ns | 0.0273 ns | 0.0228 ns | 14.603 ns | 1.17 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 27.451 ns | 0.5681 ns | 0.9174 ns | 26.928 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 16.618 ns | 0.0609 ns | 0.0540 ns | 16.613 ns | 0.59 | 0.02 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 27.694 ns | 0.5846 ns | 1.0690 ns | 27.020 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 19.865 ns | 0.0745 ns | 0.0697 ns | 19.860 ns | 0.68 | 0.01 | - | - | - | - | +| | | | | | | | | | | | | +| Linq_List_Value | List_Value | 8.626 ns | 0.0731 ns | 0.0684 ns | 8.596 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 21.742 ns | 0.1679 ns | 0.1488 ns | 21.691 ns | 2.52 | 0.03 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 75.792 ns | 0.5077 ns | 0.4749 ns | 75.774 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 26.768 ns | 0.2276 ns | 0.2018 ns | 26.724 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 22.935 ns | 0.4758 ns | 0.7266 ns | 23.214 ns | 0.84 | 0.03 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 28.074 ns | 0.5883 ns | 1.1334 ns | 27.380 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 18.836 ns | 0.4056 ns | 0.3596 ns | 18.713 ns | 0.68 | 0.02 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 8.563 ns | 0.0461 ns | 0.0408 ns | 8.560 ns | 1.00 | 0.00 | - | - | - | - | +| Hyperlinq_List_Reference | List_Reference | 24.796 ns | 0.5120 ns | 0.5478 ns | 24.930 ns | 2.89 | 0.08 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 79.490 ns | 0.3291 ns | 0.2917 ns | 79.473 ns | 1.00 | 0.00 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/SkipTakeBenchmarks.md b/Benchmarks/SkipTakeBenchmarks.md index d3bb7b8bc..c0b7c0148 100644 --- a/Benchmarks/SkipTakeBenchmarks.md +++ b/Benchmarks/SkipTakeBenchmarks.md @@ -4,63 +4,64 @@ [SkipTakeBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/SkipTakeBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` | Method | Categories | Skip | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | |------------------------------------ |-------------------------- |----- |------ |------------:|----------:|----------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 100 | 828.46 ns | 1.483 ns | 1.238 ns | 1.00 | 0.0458 | - | - | 96 B | -| StructLinq_Array | Array | 100 | 100 | 110.94 ns | 0.191 ns | 0.160 ns | 0.13 | - | - | - | - | -| Hyperlinq_Array_For | Array | 100 | 100 | 61.62 ns | 0.086 ns | 0.081 ns | 0.07 | - | - | - | - | -| Hyperlinq_Array_Foreach | Array | 100 | 100 | 297.77 ns | 0.490 ns | 0.458 ns | 0.36 | - | - | - | - | -| Hyperlinq_Span_For | Array | 100 | 100 | 61.64 ns | 0.112 ns | 0.094 ns | 0.07 | - | - | - | - | -| Hyperlinq_Span_Foreach | Array | 100 | 100 | 49.31 ns | 0.293 ns | 0.259 ns | 0.06 | - | - | - | - | -| Hyperlinq_Memory_For | Array | 100 | 100 | 59.74 ns | 0.183 ns | 0.153 ns | 0.07 | - | - | - | - | -| Hyperlinq_Memory_Foreach | Array | 100 | 100 | 60.51 ns | 0.166 ns | 0.156 ns | 0.07 | - | - | - | - | +| Linq_Array | Array | 100 | 100 | 845.25 ns | 3.560 ns | 3.330 ns | 1.00 | 0.0458 | - | - | 96 B | +| StructLinq_Array | Array | 100 | 100 | 50.19 ns | 0.296 ns | 0.262 ns | 0.06 | - | - | - | - | +| Hyperlinq_Array_For | Array | 100 | 100 | 227.75 ns | 0.798 ns | 0.707 ns | 0.27 | - | - | - | - | +| Hyperlinq_Array_Foreach | Array | 100 | 100 | 181.95 ns | 0.795 ns | 0.744 ns | 0.22 | - | - | - | - | +| Hyperlinq_Span_For | Array | 100 | 100 | 81.07 ns | 0.268 ns | 0.237 ns | 0.10 | - | - | - | - | +| Hyperlinq_Span_Foreach | Array | 100 | 100 | 172.28 ns | 0.457 ns | 0.427 ns | 0.20 | - | - | - | - | +| Hyperlinq_Memory_For | Array | 100 | 100 | 227.28 ns | 1.257 ns | 1.115 ns | 0.27 | - | - | - | - | +| Hyperlinq_Memory_Foreach | Array | 100 | 100 | 177.62 ns | 1.639 ns | 1.533 ns | 0.21 | - | - | - | - | | | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 100 | 1,523.79 ns | 2.700 ns | 2.394 ns | 1.00 | 0.0687 | - | - | 144 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 100 | 968.79 ns | 2.805 ns | 2.342 ns | 0.64 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 100 | 498.73 ns | 1.486 ns | 1.390 ns | 0.33 | - | - | - | - | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 100 | 1,451.84 ns | 4.117 ns | 3.649 ns | 1.00 | 0.0687 | - | - | 144 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 100 | 1,044.34 ns | 10.380 ns | 9.202 ns | 0.72 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 100 | 444.77 ns | 1.408 ns | 1.317 ns | 0.31 | - | - | - | - | | | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 100 | 1,532.42 ns | 5.043 ns | 4.717 ns | 1.00 | 0.0687 | - | - | 144 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 100 | 967.60 ns | 3.050 ns | 2.704 ns | 0.63 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 100 | 610.03 ns | 2.245 ns | 1.990 ns | 0.40 | - | - | - | - | +| Linq_Collection_Value | Collection_Value | 100 | 100 | 1,456.82 ns | 8.496 ns | 7.531 ns | 1.00 | 0.0687 | - | - | 144 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 100 | 1,009.74 ns | 6.760 ns | 5.992 ns | 0.69 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 100 | 599.00 ns | 2.087 ns | 1.743 ns | 0.41 | - | - | - | - | | | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 100 | 834.17 ns | 2.057 ns | 1.924 ns | 1.00 | 0.0458 | - | - | 96 B | -| StructLinq_List_Value | List_Value | 100 | 100 | 222.05 ns | 0.326 ns | 0.272 ns | 0.27 | - | - | - | - | -| Hyperlinq_List_Value_For | List_Value | 100 | 100 | 401.71 ns | 0.787 ns | 0.697 ns | 0.48 | - | - | - | - | -| Hyperlinq_List_Value_Foreach | List_Value | 100 | 100 | 248.95 ns | 1.327 ns | 1.176 ns | 0.30 | - | - | - | - | +| Linq_List_Value | List_Value | 100 | 100 | 795.57 ns | 8.248 ns | 7.312 ns | 1.00 | 0.0458 | - | - | 96 B | +| StructLinq_List_Value | List_Value | 100 | 100 | 224.50 ns | 0.712 ns | 0.594 ns | 0.28 | - | - | - | - | +| Hyperlinq_List_Value_For | List_Value | 100 | 100 | 652.01 ns | 3.322 ns | 2.944 ns | 0.82 | - | - | - | - | +| Hyperlinq_List_Value_Foreach | List_Value | 100 | 100 | 219.90 ns | 0.867 ns | 0.769 ns | 0.28 | - | - | - | - | | | | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 100 | 9,571.18 ns | 42.371 ns | 37.561 ns | 1.00 | 0.1221 | - | - | 256 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 100 | 5,312.43 ns | 16.175 ns | 14.338 ns | 0.56 | 0.0305 | - | - | 72 B | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 100 | 8,059.23 ns | 34.660 ns | 30.725 ns | 1.00 | 0.0763 | - | - | 176 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 100 | 4,271.00 ns | 11.989 ns | 10.628 ns | 0.53 | - | - | - | - | | | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 100 | 1,172.66 ns | 4.419 ns | 3.917 ns | 1.00 | 0.0687 | - | - | 144 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 100 | 706.05 ns | 1.648 ns | 1.542 ns | 0.60 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 100 | 826.26 ns | 3.009 ns | 2.349 ns | 0.70 | 0.0153 | - | - | 32 B | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 100 | 1,497.90 ns | 5.207 ns | 4.616 ns | 1.00 | 0.0687 | - | - | 144 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 100 | 1,047.97 ns | 6.071 ns | 5.679 ns | 0.70 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 100 | 1,103.82 ns | 4.664 ns | 4.362 ns | 0.74 | 0.0153 | - | - | 32 B | | | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 100 | 1,148.65 ns | 3.342 ns | 2.963 ns | 1.00 | 0.0687 | - | - | 144 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 100 | 677.29 ns | 1.542 ns | 1.367 ns | 0.59 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 100 | 931.79 ns | 2.819 ns | 2.499 ns | 0.81 | 0.0153 | - | - | 32 B | +| Linq_Collection_Reference | Collection_Reference | 100 | 100 | 1,450.03 ns | 5.975 ns | 5.296 ns | 1.00 | 0.0687 | - | - | 144 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 100 | 1,016.30 ns | 6.790 ns | 6.352 ns | 0.70 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 100 | 1,271.16 ns | 6.107 ns | 5.100 ns | 0.88 | 0.0153 | - | - | 32 B | | | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 100 | 835.78 ns | 2.241 ns | 1.986 ns | 1.00 | 0.0458 | - | - | 96 B | -| StructLinq_List_Reference | List_Reference | 100 | 100 | 704.07 ns | 1.353 ns | 1.130 ns | 0.84 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference_For | List_Reference | 100 | 100 | 377.01 ns | 0.775 ns | 0.687 ns | 0.45 | - | - | - | - | -| Hyperlinq_List_Reference_Foreach | List_Reference | 100 | 100 | 222.71 ns | 0.466 ns | 0.389 ns | 0.27 | - | - | - | - | +| Linq_List_Reference | List_Reference | 100 | 100 | 846.45 ns | 3.989 ns | 3.536 ns | 1.00 | 0.0458 | - | - | 96 B | +| StructLinq_List_Reference | List_Reference | 100 | 100 | 1,040.79 ns | 3.616 ns | 3.206 ns | 1.23 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference_For | List_Reference | 100 | 100 | 651.21 ns | 3.925 ns | 3.672 ns | 0.77 | - | - | - | - | +| Hyperlinq_List_Reference_Foreach | List_Reference | 100 | 100 | 219.32 ns | 1.068 ns | 0.892 ns | 0.26 | - | - | - | - | | | | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 100 | 9,561.55 ns | 38.920 ns | 36.406 ns | 1.00 | 0.1221 | - | - | 256 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 100 | 6,122.13 ns | 14.826 ns | 13.869 ns | 0.64 | 0.0534 | - | - | 112 B | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 100 | 8,265.76 ns | 36.451 ns | 30.438 ns | 1.00 | 0.0763 | - | - | 176 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 100 | 5,275.23 ns | 18.599 ns | 17.397 ns | 0.64 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/SumBenchmarks.md b/Benchmarks/SumBenchmarks.md index eb0ebf6ae..b9fbe9ee0 100644 --- a/Benchmarks/SumBenchmarks.md +++ b/Benchmarks/SumBenchmarks.md @@ -4,29 +4,58 @@ [SumBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/SumBenchmarks.cs) ### References: -- Linq: 5.0.2 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta34](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta34) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores -.NET Core SDK=5.0.200-preview.20614.14 - [Host] : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 Categories=Array +Runtime=.NET 6.0 ``` -| Method | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|--------------------- |------ |----------:|---------:|---------:|------:|-------:|------:|------:|----------:| -| Linq_Array | 100 | 445.32 ns | 2.467 ns | 4.753 ns | 1.00 | 0.0153 | - | - | 32 B | -| StructLinq_Array | 100 | 62.74 ns | 0.297 ns | 0.248 ns | 0.14 | - | - | - | - | -| LinqFasterSIMD_Array | 100 | 12.16 ns | 0.072 ns | 0.067 ns | 0.03 | - | - | - | - | -| Hyperlinq_Array | 100 | 19.54 ns | 0.143 ns | 0.134 ns | 0.04 | - | - | - | - | -| Hyperlinq_Span | 100 | 19.53 ns | 0.138 ns | 0.129 ns | 0.04 | - | - | - | - | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |------------:|---------:|---------:|------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 413.92 ns | 2.660 ns | 2.221 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Array | Array | 100 | 60.74 ns | 0.200 ns | 0.187 ns | 0.15 | - | - | - | - | +| LinqFasterSIMD_Array | Array | 100 | 10.63 ns | 0.075 ns | 0.071 ns | 0.03 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 22.32 ns | 0.077 ns | 0.068 ns | 0.05 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 624.83 ns | 5.028 ns | 4.457 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 574.83 ns | 2.941 ns | 2.607 ns | 0.92 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 202.11 ns | 0.557 ns | 0.493 ns | 0.32 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 616.91 ns | 4.091 ns | 3.627 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 573.70 ns | 4.680 ns | 3.908 ns | 0.93 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 208.10 ns | 0.371 ns | 0.347 ns | 0.34 | - | - | - | - | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 607.47 ns | 3.830 ns | 3.198 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_List_Value | List_Value | 100 | 223.68 ns | 0.839 ns | 0.744 ns | 0.37 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 635.26 ns | 2.463 ns | 2.057 ns | 1.05 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,612.14 ns | 6.534 ns | 5.793 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 830.85 ns | 2.255 ns | 1.999 ns | 0.52 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 616.47 ns | 2.313 ns | 2.164 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 573.38 ns | 2.951 ns | 2.616 ns | 0.93 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 597.88 ns | 3.175 ns | 2.814 ns | 0.97 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 616.39 ns | 3.075 ns | 2.726 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 575.50 ns | 3.010 ns | 2.514 ns | 0.93 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 627.72 ns | 2.465 ns | 2.306 ns | 1.02 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 620.51 ns | 3.599 ns | 3.191 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_List_Reference | List_Reference | 100 | 574.04 ns | 2.878 ns | 2.551 ns | 0.93 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 634.92 ns | 2.786 ns | 2.606 ns | 1.02 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,606.77 ns | 2.223 ns | 1.856 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,641.25 ns | 3.209 ns | 2.680 ns | 1.02 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/ToArrayBenchmarks.md b/Benchmarks/ToArrayBenchmarks.md index 108cf7257..aa3e4d4e6 100644 --- a/Benchmarks/ToArrayBenchmarks.md +++ b/Benchmarks/ToArrayBenchmarks.md @@ -4,56 +4,66 @@ [ToArrayBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToArrayBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |------------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 49.33 ns | 0.233 ns | 0.206 ns | 1.00 | 0.00 | 0.2027 | - | - | 424 B | -| StructLinq_Array | Array | 100 | 79.71 ns | 0.426 ns | 0.398 ns | 1.62 | 0.01 | 0.2027 | - | - | 424 B | -| Hyperlinq_Array | Array | 100 | 30.57 ns | 0.090 ns | 0.075 ns | 0.62 | 0.00 | 0.2027 | - | - | 424 B | -| Hyperlinq_Span | Array | 100 | 28.22 ns | 0.294 ns | 0.275 ns | 0.57 | 0.01 | 0.2027 | - | - | 424 B | -| Hyperlinq_Memory | Array | 100 | 30.64 ns | 0.181 ns | 0.160 ns | 0.62 | 0.00 | 0.2027 | - | - | 424 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 887.10 ns | 2.480 ns | 2.071 ns | 1.00 | 0.00 | 0.5655 | - | - | 1184 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 900.66 ns | 1.904 ns | 1.687 ns | 1.02 | 0.00 | 0.2174 | - | - | 456 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 517.63 ns | 1.854 ns | 1.644 ns | 0.58 | 0.00 | 0.2174 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 43.34 ns | 0.245 ns | 0.204 ns | 1.00 | 0.00 | 0.2027 | - | - | 424 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 893.50 ns | 2.616 ns | 2.184 ns | 20.62 | 0.10 | 0.2174 | - | - | 456 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 59.69 ns | 0.736 ns | 0.652 ns | 1.38 | 0.02 | 0.2180 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 45.11 ns | 0.201 ns | 0.168 ns | 1.00 | 0.00 | 0.2027 | - | - | 424 B | -| StructLinq_List_Value | List_Value | 100 | 243.02 ns | 0.931 ns | 0.871 ns | 5.39 | 0.03 | 0.2027 | - | - | 424 B | -| Hyperlinq_List_Value | List_Value | 100 | 42.65 ns | 0.234 ns | 0.196 ns | 0.95 | 0.01 | 0.2027 | - | - | 424 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 702.23 ns | 2.098 ns | 1.860 ns | 1.00 | 0.00 | 0.5655 | - | - | 1184 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 724.75 ns | 2.218 ns | 1.852 ns | 1.03 | 0.00 | 0.2174 | - | - | 456 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 789.74 ns | 2.514 ns | 2.099 ns | 1.12 | 0.00 | 0.2174 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 43.89 ns | 0.609 ns | 0.569 ns | 1.00 | 0.00 | 0.2027 | - | - | 424 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 725.74 ns | 2.660 ns | 2.488 ns | 16.54 | 0.22 | 0.2174 | - | - | 456 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 49.80 ns | 0.642 ns | 0.570 ns | 1.13 | 0.02 | 0.2142 | - | - | 448 B | -| | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 44.96 ns | 0.119 ns | 0.100 ns | 1.00 | 0.00 | 0.2027 | - | - | 424 B | -| StructLinq_List_Reference | List_Reference | 100 | 719.31 ns | 2.610 ns | 2.442 ns | 16.00 | 0.07 | 0.2174 | - | - | 456 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 45.09 ns | 0.962 ns | 0.853 ns | 1.00 | 0.02 | 0.2027 | - | - | 424 B | -| | | | | | | | | | | | | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,661.99 ns | 3.493 ns | 3.268 ns | ? | ? | 0.5646 | - | - | 1184 B | -| | | | | | | | | | | | | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,308.43 ns | 6.064 ns | 5.375 ns | ? | ? | 0.5836 | - | - | 1224 B | +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Allocated | +|---------------------------------------------- |-------------------------- |------ |------------:|-----------:|-----------:|------------:|--------------:|--------:|-------:|----------:| +| Linq_Array | Array | 100 | 143.52 ns | 13.517 ns | 39.856 ns | 135.22 ns | baseline | | 0.2027 | 424 B | +| StructLinq_Array | Array | 100 | 337.94 ns | 43.264 ns | 127.565 ns | 315.72 ns | 2.49x slower | 1.07x | 0.2027 | 424 B | +| Hyperlinq_Array | Array | 100 | 100.89 ns | 6.689 ns | 19.722 ns | 94.25 ns | 1.47x faster | 0.49x | 0.2027 | 424 B | +| Hyperlinq_Array_ArrayPool | Array | 100 | 109.18 ns | 8.605 ns | 25.373 ns | 94.61 ns | 1.36x faster | 0.43x | 0.0191 | 40 B | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,578.98 ns | 165.642 ns | 469.898 ns | 1,430.76 ns | baseline | | 0.5646 | 1,184 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,173.51 ns | 92.444 ns | 262.249 ns | 1,036.61 ns | 1.42x faster | 0.52x | 0.2174 | 456 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 1,057.32 ns | 78.396 ns | 229.922 ns | 922.84 ns | 1.56x faster | 0.59x | 0.2022 | 424 B | +| Hyperlinq_Enumerable_ArrayPool_Value | Enumerable_Value | 100 | 863.26 ns | 62.616 ns | 184.625 ns | 754.90 ns | 1.92x faster | 0.70x | 0.0191 | 40 B | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 112.45 ns | 11.254 ns | 32.109 ns | 105.85 ns | baseline | | 0.2027 | 424 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 1,352.42 ns | 123.192 ns | 345.444 ns | 1,211.76 ns | 12.70x slower | 4.34x | 0.2174 | 456 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 110.51 ns | 10.345 ns | 30.178 ns | 92.61 ns | 1.08x slower | 0.43x | 0.2027 | 424 B | +| Hyperlinq_Collection_ArrayPool_Value | Collection_Value | 100 | 108.14 ns | 7.474 ns | 22.038 ns | 96.64 ns | 1.04x slower | 0.36x | 0.0191 | 40 B | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 94.24 ns | 8.776 ns | 25.876 ns | 79.15 ns | baseline | | 0.2027 | 424 B | +| StructLinq_List_Value | List_Value | 100 | 392.66 ns | 25.951 ns | 74.459 ns | 377.42 ns | 4.44x slower | 1.21x | 0.2022 | 424 B | +| Hyperlinq_List_Value | List_Value | 100 | 110.82 ns | 10.011 ns | 29.361 ns | 92.98 ns | 1.25x slower | 0.44x | 0.2027 | 424 B | +| Hyperlinq_List_ArrayPool_Value | List_Value | 100 | 81.42 ns | 1.743 ns | 1.630 ns | 80.92 ns | 1.20x faster | 0.21x | 0.0191 | 40 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,714.55 ns | 292.913 ns | 835.697 ns | 2,397.87 ns | baseline | | 0.7668 | 1,608 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,563.81 ns | 159.957 ns | 469.125 ns | 2,376.18 ns | 1.01x slower | 0.25x | 0.5646 | 1,184 B | +| Hyperlinq_AsyncEnumerable_ArrayPool_Value | AsyncEnumerable_Value | 100 | 2,133.27 ns | 120.572 ns | 351.713 ns | 1,929.60 ns | 1.27x faster | 0.36x | 0.3815 | 800 B | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 1,663.20 ns | 164.639 ns | 467.054 ns | 1,632.07 ns | baseline | | 0.5646 | 1,184 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 915.42 ns | 17.757 ns | 28.674 ns | 906.22 ns | 1.69x faster | 0.47x | 0.2174 | 456 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 1,040.07 ns | 19.887 ns | 20.422 ns | 1,035.42 ns | 1.74x faster | 0.30x | 0.2174 | 456 B | +| Hyperlinq_Enumerable_ArrayPool_Reference | Enumerable_Reference | 100 | 1,073.81 ns | 80.581 ns | 237.595 ns | 1,011.11 ns | 1.64x faster | 0.58x | 0.0343 | 72 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 133.93 ns | 18.396 ns | 53.369 ns | 113.57 ns | baseline | | 0.2027 | 424 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 1,227.66 ns | 126.655 ns | 373.445 ns | 1,033.16 ns | 10.45x slower | 4.47x | 0.2174 | 456 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 75.55 ns | 1.647 ns | 1.286 ns | 75.54 ns | 1.55x faster | 0.65x | 0.2027 | 424 B | +| Hyperlinq_Collection_ArrayPool_Reference | Collection_Reference | 100 | 100.23 ns | 8.309 ns | 24.368 ns | 86.15 ns | 1.42x faster | 0.67x | 0.0191 | 40 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 142.59 ns | 16.619 ns | 46.051 ns | 139.86 ns | baseline | | 0.2027 | 424 B | +| StructLinq_List_Reference | List_Reference | 100 | 1,186.00 ns | 93.311 ns | 275.128 ns | 1,228.39 ns | 9.24x slower | 4.30x | 0.2174 | 456 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 99.29 ns | 8.310 ns | 23.843 ns | 88.13 ns | 1.47x faster | 0.52x | 0.2027 | 424 B | +| Hyperlinq_List_ArrayPool_Reference | List_Reference | 100 | 103.74 ns | 8.845 ns | 26.079 ns | 96.07 ns | 1.43x faster | 0.52x | 0.0191 | 40 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,852.49 ns | 227.110 ns | 636.839 ns | 2,728.24 ns | baseline | | 0.7668 | 1,608 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,577.52 ns | 161.290 ns | 473.037 ns | 2,409.79 ns | 1.13x faster | 0.32x | 0.5798 | 1,216 B | +| Hyperlinq_AsyncEnumerable_ArrayPool_Reference | AsyncEnumerable_Reference | 100 | 2,069.28 ns | 40.575 ns | 35.969 ns | 2,055.59 ns | 1.52x faster | 0.35x | 0.3967 | 832 B | diff --git a/Benchmarks/ToListBenchmarks.md b/Benchmarks/ToListBenchmarks.md index 9ed5fe136..d2b4cc10b 100644 --- a/Benchmarks/ToListBenchmarks.md +++ b/Benchmarks/ToListBenchmarks.md @@ -4,56 +4,57 @@ [ToListBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToListBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |------------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 58.20 ns | 0.494 ns | 0.438 ns | 1.00 | 0.00 | 0.2180 | - | - | 456 B | -| StructLinq_Array | Array | 100 | 114.10 ns | 0.325 ns | 0.272 ns | 1.96 | 0.01 | 0.2180 | - | - | 456 B | -| Hyperlinq_Array | Array | 100 | 49.57 ns | 0.138 ns | 0.122 ns | 0.85 | 0.01 | 0.2334 | - | - | 488 B | -| Hyperlinq_Span | Array | 100 | 160.62 ns | 0.449 ns | 0.420 ns | 2.76 | 0.02 | 0.2179 | - | - | 456 B | -| Hyperlinq_Memory | Array | 100 | 40.54 ns | 0.383 ns | 0.340 ns | 0.70 | 0.01 | 0.2180 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 893.89 ns | 2.555 ns | 2.390 ns | 1.00 | 0.00 | 0.5808 | - | - | 1216 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 934.53 ns | 2.676 ns | 2.372 ns | 1.05 | 0.00 | 0.2327 | - | - | 488 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 578.02 ns | 1.782 ns | 1.580 ns | 0.65 | 0.00 | 0.2327 | - | - | 488 B | -| | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 47.13 ns | 0.536 ns | 0.475 ns | 1.00 | 0.00 | 0.2180 | - | - | 456 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 937.11 ns | 2.386 ns | 2.115 ns | 19.89 | 0.23 | 0.2327 | - | - | 488 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 73.03 ns | 0.555 ns | 0.492 ns | 1.55 | 0.02 | 0.2333 | - | - | 488 B | -| | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 48.27 ns | 0.462 ns | 0.409 ns | 1.00 | 0.00 | 0.2180 | - | - | 456 B | -| StructLinq_List_Value | List_Value | 100 | 249.82 ns | 2.383 ns | 2.230 ns | 5.18 | 0.05 | 0.2179 | - | - | 456 B | -| Hyperlinq_List_Value | List_Value | 100 | 50.51 ns | 0.480 ns | 0.426 ns | 1.05 | 0.02 | 0.2180 | - | - | 456 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 647.78 ns | 1.861 ns | 1.650 ns | 1.00 | 0.00 | 0.5808 | - | - | 1216 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 736.91 ns | 1.475 ns | 1.380 ns | 1.14 | 0.00 | 0.2327 | - | - | 488 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 781.32 ns | 2.815 ns | 2.198 ns | 1.21 | 0.01 | 0.2327 | - | - | 488 B | -| | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 48.58 ns | 0.450 ns | 0.399 ns | 1.00 | 0.00 | 0.2180 | - | - | 456 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 727.74 ns | 1.335 ns | 1.183 ns | 14.98 | 0.12 | 0.2327 | - | - | 488 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 97.13 ns | 0.461 ns | 0.432 ns | 2.00 | 0.02 | 0.2295 | - | - | 480 B | -| | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 48.85 ns | 0.489 ns | 0.434 ns | 1.00 | 0.00 | 0.2180 | - | - | 456 B | -| StructLinq_List_Reference | List_Reference | 100 | 675.21 ns | 2.616 ns | 2.319 ns | 13.82 | 0.13 | 0.2327 | - | - | 488 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 50.82 ns | 0.335 ns | 0.297 ns | 1.04 | 0.01 | 0.2180 | - | - | 456 B | -| | | | | | | | | | | | | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,688.26 ns | 3.145 ns | 2.788 ns | ? | ? | 0.5798 | - | - | 1216 B | -| | | | | | | | | | | | | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,370.42 ns | 3.392 ns | 2.833 ns | ? | ? | 0.5989 | - | - | 1256 B | +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|----------:|----------:|------------:|--------------:|--------:|-------:|----------:| +| Linq_Array | Array | 100 | 152.3 ns | 13.07 ns | 38.55 ns | 153.11 ns | baseline | | 0.2179 | 456 B | +| StructLinq_Array | Array | 100 | 208.8 ns | 15.48 ns | 45.65 ns | 183.48 ns | 1.42x slower | 0.30x | 0.2179 | 456 B | +| Hyperlinq_Array | Array | 100 | 108.0 ns | 9.94 ns | 29.29 ns | 89.70 ns | 1.49x faster | 0.48x | 0.2180 | 456 B | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 944.9 ns | 62.47 ns | 184.20 ns | 988.12 ns | baseline | | 0.5808 | 1,216 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,145.8 ns | 103.68 ns | 304.08 ns | 966.78 ns | 1.26x slower | 0.41x | 0.2327 | 488 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 1,059.8 ns | 77.40 ns | 228.23 ns | 933.82 ns | 1.17x slower | 0.35x | 0.2174 | 456 B | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 118.8 ns | 8.42 ns | 24.82 ns | 107.77 ns | baseline | | 0.2180 | 456 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 1,177.6 ns | 97.68 ns | 288.02 ns | 1,022.94 ns | 10.33x slower | 3.33x | 0.2327 | 488 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 128.4 ns | 14.08 ns | 40.84 ns | 106.17 ns | 1.11x slower | 0.38x | 0.2179 | 456 B | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 117.5 ns | 7.59 ns | 21.42 ns | 109.69 ns | baseline | | 0.2179 | 456 B | +| StructLinq_List_Value | List_Value | 100 | 287.2 ns | 24.90 ns | 73.42 ns | 250.69 ns | 2.52x slower | 0.74x | 0.2179 | 456 B | +| Hyperlinq_List_Value | List_Value | 100 | 127.9 ns | 12.46 ns | 36.53 ns | 107.50 ns | 1.13x slower | 0.37x | 0.2179 | 456 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,460.6 ns | 109.22 ns | 318.61 ns | 2,334.36 ns | baseline | | 0.5798 | 1,216 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,772.4 ns | 175.42 ns | 517.23 ns | 2,701.79 ns | 1.15x slower | 0.27x | 0.5798 | 1,216 B | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 950.9 ns | 76.10 ns | 224.39 ns | 836.78 ns | baseline | | 0.5798 | 1,216 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 1,052.6 ns | 67.60 ns | 198.25 ns | 943.04 ns | 1.17x slower | 0.35x | 0.2327 | 488 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 1,457.2 ns | 128.46 ns | 378.76 ns | 1,202.12 ns | 1.59x slower | 0.49x | 0.2327 | 488 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 114.2 ns | 11.38 ns | 33.02 ns | 94.32 ns | baseline | | 0.2180 | 456 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 1,181.8 ns | 103.00 ns | 302.08 ns | 1,018.63 ns | 10.90x slower | 3.58x | 0.2327 | 488 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 119.5 ns | 9.30 ns | 27.42 ns | 103.49 ns | 1.11x slower | 0.35x | 0.2179 | 456 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 144.3 ns | 14.33 ns | 41.36 ns | 137.96 ns | baseline | | 0.2180 | 456 B | +| StructLinq_List_Reference | List_Reference | 100 | 1,162.4 ns | 114.20 ns | 336.71 ns | 955.59 ns | 8.67x slower | 3.17x | 0.2327 | 488 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 103.2 ns | 2.56 ns | 6.76 ns | 100.94 ns | 1.42x faster | 0.42x | 0.2179 | 456 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,565.5 ns | 129.56 ns | 382.00 ns | 2,416.41 ns | baseline | | 0.5798 | 1,216 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,867.6 ns | 191.57 ns | 564.84 ns | 2,539.05 ns | 1.14x slower | 0.29x | 0.5951 | 1,248 B | diff --git a/Benchmarks/WhereBenchmarks.md b/Benchmarks/WhereBenchmarks.md index bd7e15d15..5ed672ec5 100644 --- a/Benchmarks/WhereBenchmarks.md +++ b/Benchmarks/WhereBenchmarks.md @@ -4,52 +4,59 @@ [WhereBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|-------------------------------- |--------------------- |------ |-----------:|--------:|--------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 476.2 ns | 3.07 ns | 2.56 ns | 1.00 | 0.0229 | - | - | 48 B | -| StructLinq_Array | Array | 100 | 265.0 ns | 0.52 ns | 0.44 ns | 0.56 | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 271.2 ns | 2.27 ns | 1.90 ns | 0.57 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 326.3 ns | 4.87 ns | 4.06 ns | 0.69 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 368.9 ns | 5.80 ns | 5.42 ns | 0.77 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,348.2 ns | 2.99 ns | 2.65 ns | 1.00 | 0.0420 | - | - | 88 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,202.2 ns | 2.45 ns | 2.29 ns | 0.89 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 262.4 ns | 0.87 ns | 0.82 ns | 0.19 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 1,386.8 ns | 2.80 ns | 2.34 ns | 1.00 | 0.0420 | - | - | 88 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 1,244.6 ns | 4.08 ns | 3.82 ns | 0.90 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 272.1 ns | 0.74 ns | 0.62 ns | 0.20 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 1,341.1 ns | 5.56 ns | 4.93 ns | 1.00 | 0.0420 | - | - | 88 B | -| StructLinq_List_Value | List_Value | 100 | 660.3 ns | 3.05 ns | 2.71 ns | 0.49 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 592.8 ns | 1.64 ns | 1.54 ns | 0.44 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 1,003.0 ns | 2.76 ns | 2.45 ns | 1.00 | 0.0420 | - | - | 88 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 714.5 ns | 1.51 ns | 1.41 ns | 0.71 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 727.9 ns | 3.31 ns | 3.10 ns | 0.73 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 1,006.5 ns | 4.95 ns | 4.63 ns | 1.00 | 0.0420 | - | - | 88 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 694.3 ns | 1.96 ns | 1.73 ns | 0.69 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 727.1 ns | 3.24 ns | 2.87 ns | 0.72 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 1,006.5 ns | 2.92 ns | 2.58 ns | 1.00 | 0.0420 | - | - | 88 B | -| StructLinq_List_Reference | List_Reference | 100 | 705.6 ns | 2.00 ns | 1.77 ns | 0.70 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 578.6 ns | 2.52 ns | 2.24 ns | 0.57 | - | - | - | - | +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|---------:|----------:|-----------:|-------------:|--------:|-------:|----------:| +| Linq_Array | Array | 100 | 528.6 ns | 47.16 ns | 139.06 ns | 442.5 ns | baseline | | 0.0229 | 48 B | +| StructLinq_Array | Array | 100 | 352.1 ns | 6.21 ns | 7.85 ns | 353.0 ns | 1.50x faster | 0.45x | - | - | +| Hyperlinq_Array | Array | 100 | 342.8 ns | 4.60 ns | 4.30 ns | 341.9 ns | 1.69x faster | 0.51x | - | - | +| Hyperlinq_Span | Array | 100 | 341.2 ns | 4.70 ns | 4.40 ns | 341.4 ns | 1.70x faster | 0.52x | - | - | +| Hyperlinq_Memory | Array | 100 | 389.4 ns | 2.50 ns | 2.21 ns | 389.3 ns | 1.45x faster | 0.44x | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 700.4 ns | 60.47 ns | 177.33 ns | 589.6 ns | baseline | | 0.0420 | 88 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 484.1 ns | 6.15 ns | 5.14 ns | 482.3 ns | 1.21x faster | 0.13x | 0.0153 | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 331.4 ns | 4.30 ns | 4.02 ns | 332.4 ns | 1.77x faster | 0.21x | - | - | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 641.3 ns | 29.34 ns | 79.82 ns | 617.6 ns | baseline | | 0.0420 | 88 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 482.8 ns | 3.83 ns | 3.59 ns | 482.9 ns | 1.48x faster | 0.14x | 0.0153 | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 369.8 ns | 6.14 ns | 5.74 ns | 366.9 ns | 1.93x faster | 0.17x | - | - | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 506.5 ns | 6.73 ns | 6.30 ns | 505.0 ns | baseline | | 0.0420 | 88 B | +| StructLinq_List_Value | List_Value | 100 | 341.2 ns | 2.57 ns | 2.41 ns | 340.5 ns | 1.48x faster | 0.02x | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 406.5 ns | 3.99 ns | 3.33 ns | 405.9 ns | 1.25x faster | 0.02x | 0.0153 | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 5,012.0 ns | 45.64 ns | 40.45 ns | 5,007.0 ns | baseline | | 0.0458 | 96 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 4,672.8 ns | 28.87 ns | 25.59 ns | 4,663.9 ns | 1.07x faster | 0.01x | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 525.5 ns | 14.55 ns | 42.21 ns | 502.9 ns | baseline | | 0.0420 | 88 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 475.2 ns | 8.83 ns | 7.83 ns | 472.5 ns | 1.23x faster | 0.07x | 0.0153 | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 423.4 ns | 8.31 ns | 11.92 ns | 425.0 ns | 1.38x faster | 0.08x | 0.0153 | 32 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 506.3 ns | 6.18 ns | 5.16 ns | 507.1 ns | baseline | | 0.0420 | 88 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 481.6 ns | 3.45 ns | 3.06 ns | 481.7 ns | 1.05x faster | 0.01x | 0.0153 | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 403.2 ns | 2.46 ns | 1.92 ns | 403.6 ns | 1.25x faster | 0.01x | 0.0153 | 32 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 509.9 ns | 7.13 ns | 6.67 ns | 506.9 ns | baseline | | 0.0420 | 88 B | +| StructLinq_List_Reference | List_Reference | 100 | 486.1 ns | 4.01 ns | 3.75 ns | 485.3 ns | 1.05x faster | 0.02x | 0.0153 | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 405.0 ns | 1.29 ns | 1.14 ns | 404.9 ns | 1.26x faster | 0.02x | 0.0153 | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 5,000.2 ns | 37.85 ns | 35.41 ns | 4,984.2 ns | baseline | | 0.0458 | 96 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 4,690.6 ns | 53.19 ns | 47.15 ns | 4,666.9 ns | 1.07x faster | 0.01x | 0.0153 | 32 B | diff --git a/Benchmarks/WhereCountBenchmarks.md b/Benchmarks/WhereCountBenchmarks.md index 0a26f9f4e..aa5c6e18b 100644 --- a/Benchmarks/WhereCountBenchmarks.md +++ b/Benchmarks/WhereCountBenchmarks.md @@ -4,58 +4,59 @@ [WhereCountBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereCountBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |-----------:|--------:|--------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 636.8 ns | 3.95 ns | 3.70 ns | 1.00 | 0.0153 | - | - | 32 B | -| StructLinq_Array | Array | 100 | 234.2 ns | 0.35 ns | 0.28 ns | 0.37 | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 167.7 ns | 0.32 ns | 0.28 ns | 0.26 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 164.7 ns | 0.40 ns | 0.34 ns | 0.26 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 190.7 ns | 0.25 ns | 0.21 ns | 0.30 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,167.4 ns | 2.08 ns | 1.84 ns | 1.00 | 0.0153 | - | - | 32 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,069.0 ns | 2.98 ns | 2.79 ns | 0.92 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 204.2 ns | 0.33 ns | 0.29 ns | 0.17 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 1,167.7 ns | 3.31 ns | 2.77 ns | 1.00 | 0.0153 | - | - | 32 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 1,088.3 ns | 2.76 ns | 2.58 ns | 0.93 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 203.3 ns | 0.31 ns | 0.27 ns | 0.17 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 1,153.8 ns | 3.52 ns | 2.75 ns | 1.00 | 0.0153 | - | - | 32 B | -| StructLinq_List_Value | List_Value | 100 | 397.2 ns | 3.08 ns | 2.88 ns | 0.34 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 358.9 ns | 1.94 ns | 1.82 ns | 0.31 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,165.8 ns | 5.26 ns | 4.66 ns | 1.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 5,691.8 ns | 8.07 ns | 7.16 ns | 2.63 | 0.0610 | - | - | 136 B | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 771.0 ns | 2.55 ns | 2.13 ns | 1.00 | 0.0153 | - | - | 32 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 599.0 ns | 2.97 ns | 2.48 ns | 0.78 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 565.4 ns | 2.37 ns | 1.85 ns | 0.73 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 772.4 ns | 3.35 ns | 2.97 ns | 1.00 | 0.0153 | - | - | 32 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 585.3 ns | 3.35 ns | 3.14 ns | 0.76 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 565.4 ns | 1.26 ns | 1.18 ns | 0.73 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 768.5 ns | 4.69 ns | 4.16 ns | 1.00 | 0.0153 | - | - | 32 B | -| StructLinq_List_Reference | List_Reference | 100 | 585.7 ns | 3.06 ns | 2.86 ns | 0.76 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 372.9 ns | 0.55 ns | 0.49 ns | 0.49 | - | - | - | - | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,064.2 ns | 4.18 ns | 3.70 ns | 1.00 | 0.0191 | - | - | 40 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 5,883.8 ns | 9.57 ns | 8.49 ns | 2.85 | 0.0687 | - | - | 152 B | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 878.8 ns | 5.36 ns | 5.01 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Array | Array | 100 | 226.8 ns | 1.00 ns | 0.93 ns | 0.26 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 173.6 ns | 0.35 ns | 0.31 ns | 0.20 | - | - | - | - | +| Hyperlinq_Span | Array | 100 | 196.9 ns | 1.29 ns | 1.21 ns | 0.22 | - | - | - | - | +| Hyperlinq_Memory | Array | 100 | 199.2 ns | 0.58 ns | 0.49 ns | 0.23 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,102.0 ns | 4.29 ns | 3.58 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,050.1 ns | 7.50 ns | 7.02 ns | 0.95 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 215.4 ns | 1.72 ns | 1.52 ns | 0.20 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 1,064.8 ns | 4.86 ns | 4.54 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 1,076.9 ns | 4.56 ns | 4.27 ns | 1.01 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 218.7 ns | 1.02 ns | 0.91 ns | 0.21 | - | - | - | - | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 1,074.6 ns | 6.12 ns | 5.73 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_List_Value | List_Value | 100 | 439.7 ns | 8.58 ns | 8.02 ns | 0.41 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 823.4 ns | 12.20 ns | 10.19 ns | 0.77 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,698.2 ns | 5.19 ns | 4.34 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,514.1 ns | 6.20 ns | 5.80 ns | 1.48 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 1,066.2 ns | 6.23 ns | 5.52 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 1,082.7 ns | 5.31 ns | 4.97 ns | 1.02 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 773.4 ns | 2.93 ns | 2.60 ns | 0.73 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 1,098.8 ns | 6.60 ns | 5.85 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 1,116.5 ns | 5.08 ns | 4.24 ns | 1.02 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 737.4 ns | 4.95 ns | 4.63 ns | 0.67 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 1,101.2 ns | 3.21 ns | 3.00 ns | 1.00 | 0.0153 | - | - | 32 B | +| StructLinq_List_Reference | List_Reference | 100 | 1,032.2 ns | 4.68 ns | 3.91 ns | 0.94 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 822.6 ns | 4.43 ns | 3.70 ns | 0.75 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,706.4 ns | 7.20 ns | 6.73 ns | 1.00 | 0.0153 | - | - | 32 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,844.8 ns | 4.59 ns | 4.07 ns | 1.67 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/WhereFirstBenchmarks.md b/Benchmarks/WhereFirstBenchmarks.md index b514337ea..08d713ca2 100644 --- a/Benchmarks/WhereFirstBenchmarks.md +++ b/Benchmarks/WhereFirstBenchmarks.md @@ -4,64 +4,50 @@ [WhereFirstBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereFirstBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |---------:|--------:|--------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 178.8 ns | 0.53 ns | 0.47 ns | ? | ? | 0.0305 | - | - | 64 B | -| Hyperlinq_Span | Array | 100 | 200.7 ns | 0.37 ns | 0.33 ns | ? | ? | 0.0305 | - | - | 64 B | -| Hyperlinq_Memory | Array | 100 | 206.9 ns | 0.52 ns | 0.49 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 241.9 ns | 0.74 ns | 0.62 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 241.4 ns | 0.61 ns | 0.51 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 359.5 ns | 0.46 ns | 0.38 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 549.6 ns | 1.22 ns | 1.14 ns | ? | ? | 0.0458 | - | - | 96 B | -| | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 563.2 ns | 4.59 ns | 4.29 ns | ? | ? | 0.0458 | - | - | 96 B | -| | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_List_Reference | List_Reference | 100 | 359.1 ns | 1.21 ns | 1.01 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | - -Benchmarks with issues: - WhereFirstBenchmarks.Linq_Array: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Linq_Enumerable_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Linq_Collection_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Linq_List_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Linq_AsyncEnumerable_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Hyperlinq_AsyncEnumerable_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Linq_Enumerable_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Linq_Collection_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Linq_List_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Linq_AsyncEnumerable_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereFirstBenchmarks.Hyperlinq_AsyncEnumerable_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] +| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 628.3 ns | 3.00 ns | 2.50 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Array | Array | 100 | 211.0 ns | 1.17 ns | 0.97 ns | 0.34 | 0.00 | 0.0305 | - | - | 64 B | +| | | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 767.4 ns | 3.83 ns | 3.39 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 250.9 ns | 1.17 ns | 0.98 ns | 0.33 | 0.00 | 0.0305 | - | - | 64 B | +| | | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 784.0 ns | 4.45 ns | 3.71 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 242.3 ns | 1.46 ns | 1.30 ns | 0.31 | 0.00 | 0.0305 | - | - | 64 B | +| | | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 781.3 ns | 6.06 ns | 5.37 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_List_Value | List_Value | 100 | 788.1 ns | 6.22 ns | 5.19 ns | 1.01 | 0.01 | 0.0458 | - | - | 96 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,770.2 ns | 3.54 ns | 3.14 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,585.5 ns | 5.39 ns | 4.78 ns | 1.46 | 0.00 | 0.0305 | - | - | 64 B | +| | | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 767.2 ns | 2.33 ns | 1.95 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 840.7 ns | 2.43 ns | 2.15 ns | 1.10 | 0.00 | 0.0458 | - | - | 96 B | +| | | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 781.4 ns | 5.11 ns | 4.53 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 751.5 ns | 10.10 ns | 8.95 ns | 0.96 | 0.01 | 0.0458 | - | - | 96 B | +| | | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 807.9 ns | 2.84 ns | 2.51 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 785.2 ns | 12.49 ns | 11.68 ns | 0.97 | 0.02 | 0.0458 | - | - | 96 B | +| | | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,782.2 ns | 2.93 ns | 2.60 ns | 1.00 | 0.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,878.4 ns | 4.70 ns | 3.67 ns | 1.61 | 0.00 | 0.0458 | - | - | 96 B | diff --git a/Benchmarks/WhereSelectBenchmarks.md b/Benchmarks/WhereSelectBenchmarks.md index 2779023da..336e32ff5 100644 --- a/Benchmarks/WhereSelectBenchmarks.md +++ b/Benchmarks/WhereSelectBenchmarks.md @@ -4,52 +4,59 @@ [WhereSelectBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|-------------------------------- |--------------------- |------ |-----------:|--------:|--------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 640.4 ns | 3.21 ns | 2.84 ns | 1.00 | 0.0496 | - | - | 104 B | -| StructLinq_Array | Array | 100 | 381.8 ns | 1.63 ns | 1.36 ns | 0.60 | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 352.3 ns | 1.15 ns | 1.02 ns | 0.55 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 369.2 ns | 1.12 ns | 1.05 ns | 0.58 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 412.5 ns | 1.53 ns | 1.35 ns | 0.64 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,569.9 ns | 6.34 ns | 5.93 ns | 1.00 | 0.0725 | - | - | 152 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,353.8 ns | 3.07 ns | 2.87 ns | 0.86 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 385.8 ns | 0.86 ns | 0.80 ns | 0.25 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 1,516.2 ns | 2.88 ns | 2.69 ns | 1.00 | 0.0725 | - | - | 152 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 1,337.8 ns | 2.35 ns | 1.83 ns | 0.88 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 403.9 ns | 2.13 ns | 1.99 ns | 0.27 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 1,512.4 ns | 2.71 ns | 2.53 ns | 1.00 | 0.0725 | - | - | 152 B | -| StructLinq_List_Value | List_Value | 100 | 773.6 ns | 2.41 ns | 2.01 ns | 0.51 | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 777.2 ns | 1.50 ns | 1.33 ns | 0.51 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 1,272.0 ns | 3.50 ns | 3.10 ns | 1.00 | 0.0725 | - | - | 152 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 844.9 ns | 1.79 ns | 1.59 ns | 0.66 | 0.0153 | - | - | 32 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 875.6 ns | 1.50 ns | 1.25 ns | 0.69 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 1,268.0 ns | 4.18 ns | 3.70 ns | 1.00 | 0.0725 | - | - | 152 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 864.3 ns | 1.90 ns | 1.48 ns | 0.68 | 0.0153 | - | - | 32 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 820.6 ns | 2.38 ns | 2.11 ns | 0.65 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 1,233.5 ns | 4.33 ns | 3.61 ns | 1.00 | 0.0725 | - | - | 152 B | -| StructLinq_List_Reference | List_Reference | 100 | 845.7 ns | 3.21 ns | 2.84 ns | 0.69 | 0.0153 | - | - | 32 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 743.3 ns | 1.70 ns | 1.42 ns | 0.60 | - | - | - | - | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 685.4 ns | 4.23 ns | 3.95 ns | 1.00 | 0.0496 | - | - | 104 B | +| StructLinq_Array | Array | 100 | 372.2 ns | 2.24 ns | 2.10 ns | 0.54 | - | - | - | - | +| Hyperlinq_Array | Array | 100 | 339.9 ns | 3.48 ns | 3.08 ns | 0.50 | - | - | - | - | +| Hyperlinq_Span | Array | 100 | 330.2 ns | 1.31 ns | 1.16 ns | 0.48 | - | - | - | - | +| Hyperlinq_Memory | Array | 100 | 334.4 ns | 2.05 ns | 1.92 ns | 0.49 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,453.1 ns | 5.39 ns | 5.05 ns | 1.00 | 0.0725 | - | - | 152 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,315.9 ns | 3.66 ns | 3.42 ns | 0.91 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 369.9 ns | 2.59 ns | 2.42 ns | 0.25 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 1,480.0 ns | 12.49 ns | 11.07 ns | 1.00 | 0.0725 | - | - | 152 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 1,273.0 ns | 2.84 ns | 2.21 ns | 0.86 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 335.4 ns | 1.45 ns | 1.13 ns | 0.23 | - | - | - | - | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 1,486.9 ns | 13.11 ns | 11.62 ns | 1.00 | 0.0725 | - | - | 152 B | +| StructLinq_List_Value | List_Value | 100 | 645.3 ns | 3.29 ns | 2.92 ns | 0.43 | - | - | - | - | +| Hyperlinq_List_Value | List_Value | 100 | 1,294.9 ns | 7.31 ns | 6.84 ns | 0.87 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 4,577.4 ns | 28.26 ns | 23.60 ns | 1.00 | 0.0763 | - | - | 168 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 5,184.2 ns | 16.49 ns | 14.62 ns | 1.13 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 1,454.4 ns | 5.84 ns | 5.47 ns | 1.00 | 0.0725 | - | - | 152 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 1,282.4 ns | 2.51 ns | 2.22 ns | 0.88 | 0.0153 | - | - | 32 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 1,318.3 ns | 4.86 ns | 3.79 ns | 0.91 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 1,492.2 ns | 5.79 ns | 4.84 ns | 1.00 | 0.0725 | - | - | 152 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 1,309.7 ns | 5.51 ns | 4.89 ns | 0.88 | 0.0153 | - | - | 32 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 1,289.3 ns | 6.39 ns | 5.67 ns | 0.86 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 1,474.0 ns | 7.21 ns | 6.40 ns | 1.00 | 0.0725 | - | - | 152 B | +| StructLinq_List_Reference | List_Reference | 100 | 1,281.8 ns | 9.80 ns | 8.69 ns | 0.87 | 0.0153 | - | - | 32 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 1,285.7 ns | 8.78 ns | 8.21 ns | 0.87 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 4,546.7 ns | 24.51 ns | 21.73 ns | 1.00 | 0.0763 | - | - | 168 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 5,313.6 ns | 15.57 ns | 13.80 ns | 1.17 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/WhereSelectCountBenchmarks.md b/Benchmarks/WhereSelectCountBenchmarks.md index d92939e9c..60aa63122 100644 --- a/Benchmarks/WhereSelectCountBenchmarks.md +++ b/Benchmarks/WhereSelectCountBenchmarks.md @@ -4,45 +4,50 @@ [WhereSelectCountBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectCountBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------- |--------------------- |------ |-----------:|--------:|--------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 364.1 ns | 1.84 ns | 1.72 ns | 1.00 | 0.0496 | - | - | 104 B | -| Hyperlinq_Array | Array | 100 | 176.1 ns | 0.33 ns | 0.29 ns | 0.48 | - | - | - | - | -| Hyperlinq_Span | Array | 100 | 220.7 ns | 0.39 ns | 0.34 ns | 0.61 | - | - | - | - | -| Hyperlinq_Memory | Array | 100 | 176.2 ns | 0.28 ns | 0.26 ns | 0.48 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,221.4 ns | 2.74 ns | 2.43 ns | 1.00 | 0.0725 | - | - | 152 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 241.2 ns | 0.45 ns | 0.39 ns | 0.20 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 1,221.1 ns | 1.07 ns | 0.83 ns | 1.00 | 0.0725 | - | - | 152 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 263.9 ns | 1.00 ns | 0.94 ns | 0.22 | - | - | - | - | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 1,203.9 ns | 2.59 ns | 2.16 ns | 1.00 | 0.0725 | - | - | 152 B | -| Hyperlinq_List_Value | List_Value | 100 | 387.2 ns | 0.62 ns | 0.55 ns | 0.32 | - | - | - | - | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 874.0 ns | 4.20 ns | 3.72 ns | 1.00 | 0.0725 | - | - | 152 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 569.5 ns | 1.61 ns | 1.43 ns | 0.65 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 863.5 ns | 3.63 ns | 3.21 ns | 1.00 | 0.0725 | - | - | 152 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 517.9 ns | 0.95 ns | 0.89 ns | 0.60 | 0.0153 | - | - | 32 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 864.5 ns | 2.02 ns | 1.89 ns | 1.00 | 0.0725 | - | - | 152 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 365.0 ns | 1.01 ns | 0.94 ns | 0.42 | - | - | - | - | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 341.1 ns | 1.86 ns | 1.64 ns | 1.00 | 0.0496 | - | - | 104 B | +| Hyperlinq_Array | Array | 100 | 182.3 ns | 0.69 ns | 0.61 ns | 0.53 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,186.7 ns | 7.67 ns | 6.80 ns | 1.00 | 0.0725 | - | - | 152 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 225.2 ns | 1.24 ns | 1.10 ns | 0.19 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 1,204.4 ns | 4.62 ns | 4.32 ns | 1.00 | 0.0725 | - | - | 152 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 232.3 ns | 1.38 ns | 1.22 ns | 0.19 | - | - | - | - | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 1,189.7 ns | 6.41 ns | 5.68 ns | 1.00 | 0.0725 | - | - | 152 B | +| Hyperlinq_List_Value | List_Value | 100 | 781.3 ns | 4.77 ns | 3.98 ns | 0.66 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 4,777.6 ns | 23.18 ns | 20.55 ns | 1.00 | 0.0763 | - | - | 168 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 2,521.2 ns | 7.22 ns | 6.40 ns | 0.53 | - | - | - | - | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 1,185.0 ns | 6.96 ns | 6.17 ns | 1.00 | 0.0725 | - | - | 152 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 749.3 ns | 4.88 ns | 4.33 ns | 0.63 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 1,193.0 ns | 13.44 ns | 11.91 ns | 1.00 | 0.0725 | - | - | 152 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 749.3 ns | 2.33 ns | 2.07 ns | 0.63 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 1,201.2 ns | 15.02 ns | 13.31 ns | 1.00 | 0.0725 | - | - | 152 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 808.6 ns | 3.81 ns | 3.38 ns | 0.67 | 0.0153 | - | - | 32 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 4,771.1 ns | 19.32 ns | 18.07 ns | 1.00 | 0.0763 | - | - | 168 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 2,855.6 ns | 12.53 ns | 11.72 ns | 0.60 | 0.0153 | - | - | 32 B | diff --git a/Benchmarks/WhereSingleBenchmarks.md b/Benchmarks/WhereSingleBenchmarks.md index 49041fc1e..4053fb11f 100644 --- a/Benchmarks/WhereSingleBenchmarks.md +++ b/Benchmarks/WhereSingleBenchmarks.md @@ -4,64 +4,48 @@ [WhereSingleBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSingleBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.5.21301.5 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.26.0](https://www.nuget.org/packages/StructLinq/0.26.0) +- NetFabric.Hyperlinq: [3.0.0-beta44](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta44) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +BenchmarkDotNet=v0.13.0.1555-nightly, OS=Windows 10.0.19043.1055 (21H1/May2021Update) Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +.NET SDK=6.0.100-preview.5.21302.13 + [Host] : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT + Job-UNTOJZ : .NET 6.0.0 (6.0.21.30105), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |---------:|--------:|--------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Array | Array | 100 | 200.5 ns | 0.44 ns | 0.36 ns | ? | ? | 0.0305 | - | - | 64 B | -| Hyperlinq_Span | Array | 100 | 200.5 ns | 0.72 ns | 0.67 ns | ? | ? | 0.0305 | - | - | 64 B | -| Hyperlinq_Memory | Array | 100 | 204.3 ns | 0.36 ns | 0.30 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 218.4 ns | 0.90 ns | 0.75 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 242.9 ns | 0.80 ns | 0.75 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_List_Value | List_Value | 100 | 359.6 ns | 0.91 ns | 0.81 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 548.8 ns | 2.12 ns | 1.88 ns | ? | ? | 0.0458 | - | - | 96 B | -| | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 524.4 ns | 1.42 ns | 1.33 ns | ? | ? | 0.0458 | - | - | 96 B | -| | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_List_Reference | List_Reference | 100 | 359.0 ns | 0.65 ns | 0.57 ns | ? | ? | 0.0305 | - | - | 64 B | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | NA | NA | NA | ? | ? | - | - | - | - | - -Benchmarks with issues: - WhereSingleBenchmarks.Linq_Array: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Linq_Enumerable_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Linq_Collection_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Linq_List_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Linq_AsyncEnumerable_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Hyperlinq_AsyncEnumerable_Value: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Linq_Enumerable_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Linq_Collection_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Linq_List_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Linq_AsyncEnumerable_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] - WhereSingleBenchmarks.Hyperlinq_AsyncEnumerable_Reference: .NET Core 5.0(Runtime=.NET Core 5.0) [Count=100] +| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------------------- |-------------------------- |------ |-----------:|---------:|---------:|------:|-------:|------:|------:|----------:| +| Linq_Array | Array | 100 | 607.0 ns | 9.12 ns | 8.09 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Array | Array | 100 | 208.4 ns | 0.67 ns | 0.52 ns | 0.34 | 0.0305 | - | - | 64 B | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 761.0 ns | 4.33 ns | 3.84 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 267.5 ns | 1.15 ns | 1.02 ns | 0.35 | 0.0305 | - | - | 64 B | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 778.2 ns | 2.81 ns | 2.49 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 262.0 ns | 1.08 ns | 1.01 ns | 0.34 | 0.0305 | - | - | 64 B | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 762.9 ns | 1.55 ns | 1.30 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_List_Value | List_Value | 100 | 798.4 ns | 3.46 ns | 2.89 ns | 1.05 | 0.0458 | - | - | 96 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 1,746.6 ns | 4.35 ns | 4.06 ns | 1.00 | 0.0458 | - | - | 96 B | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 725.9 ns | 7.94 ns | 7.04 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 751.0 ns | 3.70 ns | 3.28 ns | 1.03 | 0.0458 | - | - | 96 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 724.8 ns | 9.52 ns | 8.91 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 758.4 ns | 2.32 ns | 1.94 ns | 1.04 | 0.0458 | - | - | 96 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 716.9 ns | 3.26 ns | 2.89 ns | 1.00 | 0.0458 | - | - | 96 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 828.8 ns | 4.47 ns | 3.97 ns | 1.16 | 0.0458 | - | - | 96 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 1,726.4 ns | 13.14 ns | 12.29 ns | 1.00 | 0.0458 | - | - | 96 B | diff --git a/Benchmarks/WhereToArrayBenchmarks.md b/Benchmarks/WhereToArrayBenchmarks.md index 49ef34978..1e2b1d668 100644 --- a/Benchmarks/WhereToArrayBenchmarks.md +++ b/Benchmarks/WhereToArrayBenchmarks.md @@ -4,58 +4,57 @@ [WhereToArrayBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToArrayBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 408.4 ns | 0.82 ns | 0.68 ns | 1.00 | 0.3519 | - | - | 736 B | -| StructLinq_Array | Array | 100 | 385.2 ns | 0.94 ns | 0.78 ns | 0.94 | 0.1144 | - | - | 240 B | -| Hyperlinq_Array | Array | 100 | 471.4 ns | 1.16 ns | 1.03 ns | 1.15 | 0.1144 | - | - | 240 B | -| Hyperlinq_Span | Array | 100 | 479.2 ns | 2.08 ns | 1.94 ns | 1.17 | 0.1144 | - | - | 240 B | -| Hyperlinq_Memory | Array | 100 | 520.2 ns | 1.69 ns | 1.50 ns | 1.27 | 0.1144 | - | - | 240 B | -| | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,344.1 ns | 1.97 ns | 1.75 ns | 1.00 | 0.3700 | - | - | 776 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,257.3 ns | 5.13 ns | 4.80 ns | 0.94 | 0.1297 | - | - | 272 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 506.3 ns | 3.55 ns | 3.33 ns | 0.38 | 0.1144 | - | - | 240 B | -| | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 1,221.0 ns | 2.79 ns | 2.47 ns | 1.00 | 0.3700 | - | - | 776 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 1,252.3 ns | 3.72 ns | 3.30 ns | 1.03 | 0.1297 | - | - | 272 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 573.2 ns | 9.72 ns | 8.61 ns | 0.47 | 0.1144 | - | - | 240 B | -| | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 1,205.2 ns | 2.78 ns | 2.46 ns | 1.00 | 0.3700 | - | - | 776 B | -| StructLinq_List_Value | List_Value | 100 | 787.0 ns | 1.58 ns | 1.48 ns | 0.65 | 0.1144 | - | - | 240 B | -| Hyperlinq_List_Value | List_Value | 100 | 864.1 ns | 5.16 ns | 4.57 ns | 0.72 | 0.1144 | - | - | 240 B | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 5,975.7 ns | 16.61 ns | 14.72 ns | 1.00 | 0.4578 | - | - | 960 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 6,089.1 ns | 13.45 ns | 11.92 ns | 1.02 | 0.4730 | - | - | 992 B | -| | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 797.6 ns | 6.41 ns | 5.68 ns | 1.00 | 0.3710 | - | - | 776 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 806.1 ns | 1.28 ns | 1.07 ns | 1.01 | 0.1297 | - | - | 272 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 891.9 ns | 2.48 ns | 2.07 ns | 1.12 | 0.1297 | - | - | 272 B | -| | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 792.7 ns | 12.23 ns | 9.55 ns | 1.00 | 0.3710 | - | - | 776 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 804.3 ns | 1.83 ns | 1.63 ns | 1.02 | 0.1297 | - | - | 272 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 895.5 ns | 1.64 ns | 1.46 ns | 1.13 | 0.1297 | - | - | 272 B | -| | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 794.8 ns | 2.19 ns | 1.94 ns | 1.00 | 0.3710 | - | - | 776 B | -| StructLinq_List_Reference | List_Reference | 100 | 810.0 ns | 2.25 ns | 2.11 ns | 1.02 | 0.1297 | - | - | 272 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 844.4 ns | 3.48 ns | 2.90 ns | 1.06 | 0.1144 | - | - | 240 B | -| | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 5,921.5 ns | 18.56 ns | 15.49 ns | 1.00 | 0.4578 | - | - | 960 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 6,269.7 ns | 14.95 ns | 13.98 ns | 1.06 | 0.4807 | - | - | 1008 B | +| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|-------------:|--------:|-------:|----------:| +| Linq_Array | Array | 100 | 434.2 ns | 1.36 ns | 1.27 ns | baseline | | 0.3519 | 736 B | +| StructLinq_Array | Array | 100 | 437.4 ns | 2.51 ns | 2.35 ns | 1.01x slower | 0.00x | 0.1144 | 240 B | +| Hyperlinq_Array | Array | 100 | 577.6 ns | 6.89 ns | 6.11 ns | 1.33x slower | 0.02x | 0.1144 | 240 B | +| | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 555.0 ns | 2.43 ns | 2.27 ns | baseline | | 0.3710 | 776 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 616.8 ns | 1.73 ns | 1.45 ns | 1.11x slower | 0.00x | 0.1297 | 272 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 614.7 ns | 3.39 ns | 3.00 ns | 1.11x slower | 0.01x | 0.1144 | 240 B | +| | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 584.4 ns | 3.80 ns | 3.56 ns | baseline | | 0.3710 | 776 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 610.2 ns | 4.36 ns | 3.86 ns | 1.04x slower | 0.01x | 0.1297 | 272 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 596.2 ns | 5.27 ns | 4.11 ns | 1.02x slower | 0.01x | 0.1144 | 240 B | +| | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 576.4 ns | 2.46 ns | 2.06 ns | baseline | | 0.3710 | 776 B | +| StructLinq_List_Value | List_Value | 100 | 502.4 ns | 3.02 ns | 2.82 ns | 1.15x faster | 0.01x | 0.1144 | 240 B | +| Hyperlinq_List_Value | List_Value | 100 | 750.1 ns | 5.04 ns | 4.72 ns | 1.30x slower | 0.01x | 0.1297 | 272 B | +| | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 5,109.9 ns | 21.88 ns | 20.47 ns | baseline | | 0.4501 | 952 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 3,017.0 ns | 10.32 ns | 9.66 ns | 1.69x faster | 0.01x | 0.3433 | 720 B | +| | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 555.3 ns | 2.73 ns | 2.56 ns | baseline | | 0.3710 | 776 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 616.8 ns | 8.58 ns | 8.02 ns | 1.11x slower | 0.02x | 0.1297 | 272 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 717.4 ns | 13.31 ns | 11.11 ns | 1.29x slower | 0.02x | 0.1297 | 272 B | +| | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 585.6 ns | 11.67 ns | 23.58 ns | baseline | | 0.3710 | 776 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 612.1 ns | 11.94 ns | 14.66 ns | 1.03x slower | 0.06x | 0.1297 | 272 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 712.0 ns | 14.18 ns | 18.44 ns | 1.20x slower | 0.07x | 0.1297 | 272 B | +| | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 577.9 ns | 3.49 ns | 3.09 ns | baseline | | 0.3710 | 776 B | +| StructLinq_List_Reference | List_Reference | 100 | 601.2 ns | 0.76 ns | 0.60 ns | 1.04x slower | 0.01x | 0.1297 | 272 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 725.8 ns | 4.94 ns | 4.62 ns | 1.26x slower | 0.01x | 0.1297 | 272 B | +| | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 5,201.5 ns | 24.53 ns | 22.94 ns | baseline | | 0.4501 | 952 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 3,198.6 ns | 10.74 ns | 8.97 ns | 1.63x faster | 0.01x | 0.3586 | 752 B | diff --git a/Benchmarks/WhereToListBenchmarks.md b/Benchmarks/WhereToListBenchmarks.md index dbab1aea2..a51bbca4b 100644 --- a/Benchmarks/WhereToListBenchmarks.md +++ b/Benchmarks/WhereToListBenchmarks.md @@ -4,58 +4,57 @@ [WhereToListBenchmarks.cs](../NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToListBenchmarks.cs) ### References: -- Linq: 4.8.4300.0 +- Linq: 6.0.0-preview.7.21377.19 - System.Linq.Async: [5.0.0](https://www.nuget.org/packages/System.Linq.Async/5.0.0) - System.Interactive: [5.0.0](https://www.nuget.org/packages/System.Interactive/5.0.0) - System.Interactive.Async: [5.0.0](https://www.nuget.org/packages/System.Interactive.Async/5.0.0) -- StructLinq: [0.25.3](https://www.nuget.org/packages/StructLinq/0.25.3) -- NetFabric.Hyperlinq: [3.0.0-beta29](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta29) +- StructLinq: [0.27.0](https://www.nuget.org/packages/StructLinq/0.27.0) +- NetFabric.Hyperlinq: [3.0.0-beta45](https://www.nuget.org/packages/NetFabric.Hyperlinq/3.0.0-beta45) ### Results: ``` ini -BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 -Intel Core i7-7567U CPU 3.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores - [Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT - .NET Core 5.0 : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT +BenchmarkDotNet=v0.13.1.1606-nightly, OS=macOS Catalina 10.15.7 (19H1323) [Darwin 19.6.0] +Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores +.NET SDK=6.0.100-preview.7.21379.14 + [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT + .NET 6 PGO : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT -Job=.NET Core 5.0 Runtime=.NET Core 5.0 +Job=.NET 6 PGO EnvironmentVariables=COMPlus_ReadyToRun=0,COMPlus_TC_QuickJitForLoops=1,COMPlus_TieredPGO=1 Runtime=.NET 6.0 ``` -| Method | Categories | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| -| Linq_Array | Array | 100 | 400.6 ns | 2.94 ns | 2.60 ns | 1.00 | 0.00 | 0.3328 | - | - | 696 B | -| StructLinq_Array | Array | 100 | 431.3 ns | 5.80 ns | 4.85 ns | 1.08 | 0.01 | 0.1297 | - | - | 272 B | -| Hyperlinq_Array | Array | 100 | 514.6 ns | 4.31 ns | 3.82 ns | 1.28 | 0.01 | 0.1297 | - | - | 272 B | -| Hyperlinq_Span | Array | 100 | 505.9 ns | 5.18 ns | 4.85 ns | 1.26 | 0.01 | 0.1297 | - | - | 272 B | -| Hyperlinq_Memory | Array | 100 | 484.4 ns | 5.52 ns | 4.90 ns | 1.21 | 0.01 | 0.1297 | - | - | 272 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Value | Enumerable_Value | 100 | 1,340.7 ns | 15.61 ns | 13.84 ns | 1.00 | 0.00 | 0.3510 | - | - | 736 B | -| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 1,269.4 ns | 10.89 ns | 9.10 ns | 0.95 | 0.01 | 0.1450 | - | - | 304 B | -| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 592.3 ns | 9.60 ns | 8.51 ns | 0.44 | 0.01 | 0.1297 | - | - | 272 B | -| | | | | | | | | | | | | -| Linq_Collection_Value | Collection_Value | 100 | 1,246.4 ns | 11.41 ns | 10.68 ns | 1.00 | 0.00 | 0.3510 | - | - | 736 B | -| StructLinq_Collection_Value | Collection_Value | 100 | 1,298.3 ns | 21.72 ns | 19.25 ns | 1.04 | 0.01 | 0.1450 | - | - | 304 B | -| Hyperlinq_Collection_Value | Collection_Value | 100 | 553.5 ns | 8.56 ns | 8.00 ns | 0.44 | 0.01 | 0.1297 | - | - | 272 B | -| | | | | | | | | | | | | -| Linq_List_Value | List_Value | 100 | 1,228.4 ns | 4.36 ns | 3.86 ns | 1.00 | 0.00 | 0.3510 | - | - | 736 B | -| StructLinq_List_Value | List_Value | 100 | 823.2 ns | 4.09 ns | 3.41 ns | 0.67 | 0.00 | 0.1297 | - | - | 272 B | -| Hyperlinq_List_Value | List_Value | 100 | 912.7 ns | 6.66 ns | 6.23 ns | 0.74 | 0.00 | 0.1297 | - | - | 272 B | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 6,239.2 ns | 28.51 ns | 23.81 ns | 1.00 | 0.00 | 0.3586 | - | - | 752 B | -| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 6,028.3 ns | 40.70 ns | 33.98 ns | 0.97 | 0.00 | 0.3738 | - | - | 784 B | -| | | | | | | | | | | | | -| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 923.7 ns | 9.56 ns | 8.94 ns | 1.00 | 0.00 | 0.3519 | - | - | 736 B | -| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 870.5 ns | 6.22 ns | 4.86 ns | 0.94 | 0.01 | 0.1450 | - | - | 304 B | -| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 951.5 ns | 12.88 ns | 12.05 ns | 1.03 | 0.02 | 0.1450 | - | - | 304 B | -| | | | | | | | | | | | | -| Linq_Collection_Reference | Collection_Reference | 100 | 825.7 ns | 6.73 ns | 6.30 ns | 1.00 | 0.00 | 0.3519 | - | - | 736 B | -| StructLinq_Collection_Reference | Collection_Reference | 100 | 856.7 ns | 8.19 ns | 7.66 ns | 1.04 | 0.01 | 0.1450 | - | - | 304 B | -| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 954.3 ns | 6.18 ns | 5.47 ns | 1.16 | 0.01 | 0.1450 | - | - | 304 B | -| | | | | | | | | | | | | -| Linq_List_Reference | List_Reference | 100 | 1,044.1 ns | 10.54 ns | 8.80 ns | 1.00 | 0.00 | 0.3510 | - | - | 736 B | -| StructLinq_List_Reference | List_Reference | 100 | 868.8 ns | 14.72 ns | 13.05 ns | 0.83 | 0.01 | 0.1450 | - | - | 304 B | -| Hyperlinq_List_Reference | List_Reference | 100 | 914.0 ns | 4.03 ns | 3.15 ns | 0.88 | 0.01 | 0.1297 | - | - | 272 B | -| | | | | | | | | | | | | -| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 6,083.8 ns | 25.51 ns | 21.30 ns | 1.00 | 0.00 | 0.3586 | - | - | 752 B | -| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 6,889.0 ns | 23.42 ns | 20.76 ns | 1.13 | 0.00 | 0.3815 | - | - | 800 B | +| Method | Categories | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Allocated | +|------------------------------------ |-------------------------- |------ |-----------:|---------:|---------:|-----------:|-------------:|--------:|-------:|----------:| +| Linq_Array | Array | 100 | 397.0 ns | 1.32 ns | 1.10 ns | 396.7 ns | baseline | | 0.3328 | 696 B | +| StructLinq_Array | Array | 100 | 467.5 ns | 6.04 ns | 5.35 ns | 466.2 ns | 1.18x slower | 0.01x | 0.1297 | 272 B | +| Hyperlinq_Array | Array | 100 | 616.5 ns | 10.59 ns | 8.84 ns | 617.4 ns | 1.55x slower | 0.02x | 0.1297 | 272 B | +| | | | | | | | | | | | +| Linq_Enumerable_Value | Enumerable_Value | 100 | 516.6 ns | 5.42 ns | 5.07 ns | 515.2 ns | baseline | | 0.3519 | 736 B | +| StructLinq_Enumerable_Value | Enumerable_Value | 100 | 611.8 ns | 6.76 ns | 6.00 ns | 610.1 ns | 1.18x slower | 0.02x | 0.1450 | 304 B | +| Hyperlinq_Enumerable_Value | Enumerable_Value | 100 | 668.4 ns | 16.30 ns | 43.80 ns | 649.7 ns | 1.35x slower | 0.10x | 0.1297 | 272 B | +| | | | | | | | | | | | +| Linq_Collection_Value | Collection_Value | 100 | 525.4 ns | 5.74 ns | 5.37 ns | 523.4 ns | baseline | | 0.3519 | 736 B | +| StructLinq_Collection_Value | Collection_Value | 100 | 576.8 ns | 4.23 ns | 3.54 ns | 576.6 ns | 1.10x slower | 0.01x | 0.1450 | 304 B | +| Hyperlinq_Collection_Value | Collection_Value | 100 | 703.4 ns | 15.04 ns | 41.93 ns | 687.7 ns | 1.41x slower | 0.10x | 0.1297 | 272 B | +| | | | | | | | | | | | +| Linq_List_Value | List_Value | 100 | 517.3 ns | 5.27 ns | 4.67 ns | 515.5 ns | baseline | | 0.3519 | 736 B | +| StructLinq_List_Value | List_Value | 100 | 536.5 ns | 3.80 ns | 3.37 ns | 535.7 ns | 1.04x slower | 0.01x | 0.1297 | 272 B | +| Hyperlinq_List_Value | List_Value | 100 | 836.0 ns | 9.89 ns | 7.72 ns | 835.3 ns | 1.62x slower | 0.02x | 0.1450 | 304 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 5,264.3 ns | 17.15 ns | 14.32 ns | 5,263.1 ns | baseline | | 0.3510 | 744 B | +| Hyperlinq_AsyncEnumerable_Value | AsyncEnumerable_Value | 100 | 3,202.6 ns | 56.35 ns | 47.05 ns | 3,200.3 ns | 1.64x faster | 0.03x | 0.3586 | 752 B | +| | | | | | | | | | | | +| Linq_Enumerable_Reference | Enumerable_Reference | 100 | 520.4 ns | 6.68 ns | 5.92 ns | 517.4 ns | baseline | | 0.3519 | 736 B | +| StructLinq_Enumerable_Reference | Enumerable_Reference | 100 | 610.1 ns | 5.59 ns | 4.95 ns | 609.4 ns | 1.17x slower | 0.02x | 0.1450 | 304 B | +| Hyperlinq_Enumerable_Reference | Enumerable_Reference | 100 | 770.1 ns | 15.17 ns | 19.72 ns | 768.2 ns | 1.47x slower | 0.04x | 0.1450 | 304 B | +| | | | | | | | | | | | +| Linq_Collection_Reference | Collection_Reference | 100 | 519.3 ns | 4.43 ns | 4.14 ns | 518.1 ns | baseline | | 0.3519 | 736 B | +| StructLinq_Collection_Reference | Collection_Reference | 100 | 624.5 ns | 18.32 ns | 49.83 ns | 606.0 ns | 1.22x slower | 0.11x | 0.1450 | 304 B | +| Hyperlinq_Collection_Reference | Collection_Reference | 100 | 754.0 ns | 11.22 ns | 9.37 ns | 753.6 ns | 1.45x slower | 0.02x | 0.1450 | 304 B | +| | | | | | | | | | | | +| Linq_List_Reference | List_Reference | 100 | 518.8 ns | 5.66 ns | 5.29 ns | 517.9 ns | baseline | | 0.3519 | 736 B | +| StructLinq_List_Reference | List_Reference | 100 | 652.0 ns | 12.89 ns | 18.07 ns | 648.6 ns | 1.25x slower | 0.03x | 0.1450 | 304 B | +| Hyperlinq_List_Reference | List_Reference | 100 | 815.1 ns | 16.32 ns | 27.71 ns | 809.2 ns | 1.58x slower | 0.06x | 0.1450 | 304 B | +| | | | | | | | | | | | +| Linq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 5,203.8 ns | 20.01 ns | 16.71 ns | 5,196.0 ns | baseline | | 0.3510 | 744 B | +| Hyperlinq_AsyncEnumerable_Reference | AsyncEnumerable_Reference | 100 | 3,274.2 ns | 49.93 ns | 46.71 ns | 3,252.6 ns | 1.59x faster | 0.02x | 0.3738 | 784 B | diff --git a/Directory.Build.props b/Directory.Build.props index c658797b2..ce2d72bbe 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,8 +4,9 @@ Antao Almada Copyright 2019-2021 Antao Almada - 9.0 + latest strict + enable diff --git a/Icon.png b/Icon.png index 278ddc671..baf66818c 100644 Binary files a/Icon.png and b/Icon.png differ diff --git a/NetFabric.Hyperlinq.Abstractions/AsyncFunctionWrapper.cs b/NetFabric.Hyperlinq.Abstractions/AsyncFunctionWrapper.cs index 32621771c..866062a99 100644 --- a/NetFabric.Hyperlinq.Abstractions/AsyncFunctionWrapper.cs +++ b/NetFabric.Hyperlinq.Abstractions/AsyncFunctionWrapper.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -12,8 +13,12 @@ namespace NetFabric.Hyperlinq public AsyncFunctionWrapper(Func> function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask InvokeAsync(T arg, CancellationToken cancellationToken) => function(arg, cancellationToken); + + public static implicit operator AsyncFunctionWrapper(Func> func) + => new(func); } public readonly struct AsyncFunctionWrapper @@ -24,8 +29,12 @@ public ValueTask InvokeAsync(T arg, CancellationToken cancellationToken public AsyncFunctionWrapper(Func> function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask InvokeAsync(T1 arg1, T2 arg2, CancellationToken cancellationToken) => function(arg1, arg2, cancellationToken); + + public static implicit operator AsyncFunctionWrapper(Func> func) + => new(func); } public readonly struct AsyncFunctionWrapper @@ -36,8 +45,12 @@ public ValueTask InvokeAsync(T1 arg1, T2 arg2, CancellationToken cancel public AsyncFunctionWrapper(Func> function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, CancellationToken cancellationToken) => function(arg1, arg2, arg3, cancellationToken); + + public static implicit operator AsyncFunctionWrapper(Func> func) + => new(func); } public readonly struct AsyncFunctionWrapper @@ -48,8 +61,12 @@ public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, CancellationTok public AsyncFunctionWrapper(Func> function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, CancellationToken cancellationToken) => function(arg1, arg2, arg3, arg4, cancellationToken); + + public static implicit operator AsyncFunctionWrapper(Func> func) + => new(func); } public readonly struct AsyncFunctionWrapper @@ -60,8 +77,12 @@ public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, Cancel public AsyncFunctionWrapper(Func> function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, CancellationToken cancellationToken) => function(arg1, arg2, arg3, arg4, arg5, cancellationToken); + + public static implicit operator AsyncFunctionWrapper(Func> func) + => new(func); } public readonly struct AsyncFunctionWrapper @@ -72,8 +93,12 @@ public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg public AsyncFunctionWrapper(Func> function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, CancellationToken cancellationToken) => function(arg1, arg2, arg3, arg4, arg5, arg6, cancellationToken); + + public static implicit operator AsyncFunctionWrapper(Func> func) + => new(func); } public readonly struct AsyncFunctionWrapper @@ -84,8 +109,12 @@ public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg public AsyncFunctionWrapper(Func> function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, CancellationToken cancellationToken) => function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, cancellationToken); + + public static implicit operator AsyncFunctionWrapper(Func> func) + => new(func); } public readonly struct AsyncFunctionWrapper @@ -96,8 +125,12 @@ public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg public AsyncFunctionWrapper(Func> function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, CancellationToken cancellationToken) => function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, cancellationToken); + + public static implicit operator AsyncFunctionWrapper(Func> func) + => new(func); } public readonly struct AsyncFunctionWrapper @@ -108,7 +141,11 @@ public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg public AsyncFunctionWrapper(Func> function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask InvokeAsync(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, CancellationToken cancellationToken) => function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, cancellationToken); + + public static implicit operator AsyncFunctionWrapper(Func> func) + => new(func); } } diff --git a/NetFabric.Hyperlinq.Abstractions/FunctionIn.cs b/NetFabric.Hyperlinq.Abstractions/FunctionIn.cs index e4e4ab4ac..b10e4d3c8 100644 --- a/NetFabric.Hyperlinq.Abstractions/FunctionIn.cs +++ b/NetFabric.Hyperlinq.Abstractions/FunctionIn.cs @@ -2,5 +2,5 @@ { public delegate TResult FunctionIn(in T arg); - public delegate TResult FunctionIn(in T1 arg, T2 arg2); + public delegate TResult FunctionIn(in T1 arg, T2 arg2); } diff --git a/NetFabric.Hyperlinq.Abstractions/FunctionInWrapper.cs b/NetFabric.Hyperlinq.Abstractions/FunctionInWrapper.cs index 535c84056..e91f77875 100644 --- a/NetFabric.Hyperlinq.Abstractions/FunctionInWrapper.cs +++ b/NetFabric.Hyperlinq.Abstractions/FunctionInWrapper.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { @@ -10,8 +11,12 @@ namespace NetFabric.Hyperlinq public FunctionInWrapper(FunctionIn function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(in T arg) => function(arg); + + public static implicit operator FunctionInWrapper(FunctionIn func) + => new(func); } public readonly struct FunctionInWrapper @@ -22,7 +27,11 @@ public TResult Invoke(in T arg) public FunctionInWrapper(FunctionIn function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(in T1 arg1, T2 arg2) => function(arg1, arg2); + + public static implicit operator FunctionInWrapper(FunctionIn func) + => new(func); } } diff --git a/NetFabric.Hyperlinq.Abstractions/FunctionWrapper.cs b/NetFabric.Hyperlinq.Abstractions/FunctionWrapper.cs index 2802ed999..7cd133f9f 100644 --- a/NetFabric.Hyperlinq.Abstractions/FunctionWrapper.cs +++ b/NetFabric.Hyperlinq.Abstractions/FunctionWrapper.cs @@ -1,7 +1,24 @@ using System; +using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { + public readonly struct FunctionWrapper + : IFunction + { + readonly Func function; + + public FunctionWrapper(Func function) + => this.function = function ?? throw new ArgumentNullException(nameof(function)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TResult Invoke() + => function(); + + public static implicit operator FunctionWrapper(Func func) + => new(func); + } + public readonly struct FunctionWrapper : IFunction { @@ -10,8 +27,12 @@ namespace NetFabric.Hyperlinq public FunctionWrapper(Func function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(T arg) => function(arg); + + public static implicit operator FunctionWrapper(Func func) + => new(func); } public readonly struct FunctionWrapper @@ -22,8 +43,12 @@ public TResult Invoke(T arg) public FunctionWrapper(Func function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(T1 arg1, T2 arg2) => function(arg1, arg2); + + public static implicit operator FunctionWrapper(Func func) + => new(func); } public readonly struct FunctionWrapper @@ -34,8 +59,12 @@ public TResult Invoke(T1 arg1, T2 arg2) public FunctionWrapper(Func function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(T1 arg1, T2 arg2, T3 arg3) => function(arg1, arg2, arg3); + + public static implicit operator FunctionWrapper(Func func) + => new(func); } public readonly struct FunctionWrapper @@ -46,8 +75,12 @@ public TResult Invoke(T1 arg1, T2 arg2, T3 arg3) public FunctionWrapper(Func function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4) => function(arg1, arg2, arg3, arg4); + + public static implicit operator FunctionWrapper(Func func) + => new(func); } public readonly struct FunctionWrapper @@ -58,8 +91,12 @@ public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4) public FunctionWrapper(Func function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) => function(arg1, arg2, arg3, arg4, arg5); + + public static implicit operator FunctionWrapper(Func func) + => new(func); } public readonly struct FunctionWrapper @@ -70,8 +107,12 @@ public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) public FunctionWrapper(Func function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) => function(arg1, arg2, arg3, arg4, arg5, arg6); + + public static implicit operator FunctionWrapper(Func func) + => new(func); } public readonly struct FunctionWrapper @@ -82,8 +123,12 @@ public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) public FunctionWrapper(Func function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) => function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + + public static implicit operator FunctionWrapper(Func func) + => new(func); } public readonly struct FunctionWrapper @@ -94,8 +139,12 @@ public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 a public FunctionWrapper(Func function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) => function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + + public static implicit operator FunctionWrapper(Func func) + => new(func); } public readonly struct FunctionWrapper @@ -106,7 +155,11 @@ public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 a public FunctionWrapper(Func function) => this.function = function ?? throw new ArgumentNullException(nameof(function)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) => function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + + public static implicit operator FunctionWrapper(Func func) + => new(func); } } diff --git a/NetFabric.Hyperlinq.Abstractions/IEnumeratorRef.cs b/NetFabric.Hyperlinq.Abstractions/IEnumeratorRef.cs deleted file mode 100644 index 8ca23bd73..000000000 --- a/NetFabric.Hyperlinq.Abstractions/IEnumeratorRef.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace NetFabric.Hyperlinq -{ - public interface IEnumeratorRef - { - ref T Current { get; } - - bool MoveNext(); - } -} diff --git a/NetFabric.Hyperlinq.Abstractions/IFunction.cs b/NetFabric.Hyperlinq.Abstractions/IFunction.cs index ee309ec5b..1133f3133 100644 --- a/NetFabric.Hyperlinq.Abstractions/IFunction.cs +++ b/NetFabric.Hyperlinq.Abstractions/IFunction.cs @@ -1,47 +1,64 @@ -namespace NetFabric.Hyperlinq +using System.Diagnostics.Contracts; + +namespace NetFabric.Hyperlinq { + public interface IFunction + { + [Pure] + TResult Invoke(); + } + public interface IFunction { + [Pure] TResult Invoke(T arg); } public interface IFunction { + [Pure] TResult Invoke(T1 arg1, T2 arg2); } public interface IFunction { + [Pure] TResult Invoke(T1 arg1, T2 arg2, T3 arg3); } public interface IFunction { + [Pure] TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4); } public interface IFunction { + [Pure] TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); } public interface IFunction { + [Pure] TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); } public interface IFunction { + [Pure] TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); } public interface IFunction { + [Pure] TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); } public interface IFunction { + [Pure] TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); } } diff --git a/NetFabric.Hyperlinq.Abstractions/NetFabric.Hyperlinq.Abstractions.csproj b/NetFabric.Hyperlinq.Abstractions/NetFabric.Hyperlinq.Abstractions.csproj index 35debdd98..a7ecc6c65 100644 --- a/NetFabric.Hyperlinq.Abstractions/NetFabric.Hyperlinq.Abstractions.csproj +++ b/NetFabric.Hyperlinq.Abstractions/NetFabric.Hyperlinq.Abstractions.csproj @@ -1,17 +1,18 @@  - net461;net5.0;netstandard2.0;netstandard2.1 + net5.0;netstandard2.0;netstandard2.1 NetFabric.Hyperlinq.Abstractions NetFabric.Hyperlinq.Abstractions Abstractions for high performance enumeration. - 1.1.0-beta01 + 1.3.0 Icon.png LICENSE netfabric, hyperlinq, abstractions, linq, enumeration, performance true - Added IFunctionIn and related interfaces. - enable + true + snupkg + diff --git a/NetFabric.Hyperlinq.Abstractions/ValueEnumerable.cs b/NetFabric.Hyperlinq.Abstractions/ValueEnumerable.cs index 05a2cc620..d4078c94f 100644 --- a/NetFabric.Hyperlinq.Abstractions/ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Abstractions/ValueEnumerable.cs @@ -5,9 +5,7 @@ namespace NetFabric.Hyperlinq { public interface IValueEnumerable : IEnumerable - where TEnumerator - : struct - , IEnumerator + where TEnumerator : struct, IEnumerator { [return: NotNull] new TEnumerator GetEnumerator(); } @@ -15,26 +13,14 @@ where TEnumerator public interface IValueReadOnlyCollection : IReadOnlyCollection , IValueEnumerable - where TEnumerator - : struct - , IEnumerator + where TEnumerator : struct, IEnumerator { } public interface IValueReadOnlyList : IReadOnlyList , IValueReadOnlyCollection - where TEnumerator - : struct - , IEnumerator + where TEnumerator : struct, IEnumerator { } - - public interface IValueEnumerableRef - where TEnumerator - : struct - , IEnumeratorRef - { - [return: NotNull] TEnumerator GetEnumerator(); - } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AggressiveInliningBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AggressiveInliningBenchmarks.cs new file mode 100644 index 000000000..d33ec4e09 --- /dev/null +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AggressiveInliningBenchmarks.cs @@ -0,0 +1,82 @@ +using BenchmarkDotNet.Attributes; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq.Benchmarks.Benchmarks +{ + public class AggressiveInliningBenchmarks + { + const int seed = 2982; + int[]? array; + + [Params(1_000)] + public int Count { get; set; } + + [GlobalSetup] + public void GlobalSetup() + => array = Utils.GetRandomValues(seed, Count); + + [Benchmark(Baseline = true)] + public int Baseline() + { + var enumerator = new Enumerator(array!); + var sum = 0; + while (enumerator.MoveNext()) + sum += enumerator.Current; + return sum; + } + + [Benchmark] + public int AggressiveInlining() + { + var enumerator = new AggressiveInliningEnumerator(array!); + var sum = 0; + while (enumerator.MoveNext()) + sum += enumerator.Current; + return sum; + } + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + { + readonly TSource[] source; + int index; + + public Enumerator(TSource[] source) + { + this.source = source; + index = -1; + } + + public readonly TSource Current + => source[index]; + + public bool MoveNext() + => ++index < source.Length; + } + + [StructLayout(LayoutKind.Auto)] + public struct AggressiveInliningEnumerator + { + readonly TSource[] source; + int index; + + public AggressiveInliningEnumerator(TSource[] source) + { + this.source = source; + index = -1; + } + + public readonly TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + => ++index < source.Length; + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AllBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AllBenchmarks.cs index 57aa1d4aa..0658622f3 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AllBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AllBenchmarks.cs @@ -1,6 +1,5 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using System; using System.Linq; using System.Threading.Tasks; @@ -13,75 +12,65 @@ public class AllBenchmarks : RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public bool Linq_Array() - => Enumerable.All(array, _ => true); + => array.All(_ => true); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public bool Linq_Enumerable_Value() - => Enumerable.All(enumerableValue, _ => true); + => enumerableValue.All(_ => true); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public bool Linq_Collection_Value() - => Enumerable.All(collectionValue, _ => true); + => collectionValue.All(_ => true); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public bool Linq_List_Value() - => Enumerable.All(listValue, _ => true); + => listValue.All(_ => true); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.AllAsync(asyncEnumerableValue, _ => true); + => asyncEnumerableValue.AllAsync(_ => true); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public bool Linq_Enumerable_Reference() - => Enumerable.All(enumerableReference, _ => true); + => enumerableReference.All(_ => true); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public bool Linq_Collection_Reference() - => Enumerable.All(collectionReference, _ => true); + => collectionReference.All(_ => true); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public bool Linq_List_Reference() - => Enumerable.All(listReference, _ => true); + => listReference.All(_ => true); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.AllAsync(asyncEnumerableReference, _ => true); + => asyncEnumerableReference.AllAsync(_ => true); // --------------------------------------------------------------------- [BenchmarkCategory("Array")] [Benchmark] public bool Hyperlinq_Array() - => array.All(_ => true); - - [BenchmarkCategory("Array")] - [Benchmark] - public bool Hyperlinq_Span() - => array.AsSpan().All(_ => true); - - [BenchmarkCategory("Array")] - [Benchmark] - public bool Hyperlinq_Memory() - => memory.AsValueEnumerable().All(_ => true); + => array.AsValueEnumerable().All(_ => true); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public bool Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .All(_ => true); [BenchmarkCategory("Collection_Value")] [Benchmark] public bool Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .All(_ => true); [BenchmarkCategory("List_Value")] @@ -95,7 +84,7 @@ public bool Hyperlinq_List_Value() [Benchmark] public ValueTask Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) + .AsAsyncValueEnumerable() .AllAsync((item, _) => new ValueTask((item & 0x01) == 0)); [BenchmarkCategory("Enumerable_Reference")] diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyBenchmarks.cs index d74f888b4..ac880e5ea 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyBenchmarks.cs @@ -1,6 +1,5 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using System; using System.Linq; using System.Threading.Tasks; @@ -13,75 +12,65 @@ public class AnyBenchmarks: RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public bool Linq_Array() - => Enumerable.Any(array); + => array.Any(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public bool Linq_Enumerable_Value() - => Enumerable.Any(enumerableValue); + => enumerableValue.Any(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public bool Linq_Collection_Value() - => Enumerable.Any(collectionValue); + => collectionValue.Any(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public bool Linq_List_Value() - => Enumerable.Any(listValue); + => listValue.Any(); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.AnyAsync(asyncEnumerableValue); + => asyncEnumerableValue.AnyAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public bool Linq_Enumerable_Reference() - => Enumerable.Any(enumerableReference); + => enumerableReference.Any(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public bool Linq_Collection_Reference() - => Enumerable.Any(collectionReference); + => collectionReference.Any(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public bool Linq_List_Reference() - => Enumerable.Any(listReference); + => listReference.Any(); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.AnyAsync(asyncEnumerableReference); + => asyncEnumerableReference.AnyAsync(); // --------------------------------------------------------------------- [BenchmarkCategory("Array")] [Benchmark] public bool Hyperlinq_Array() - => array.Any(); - - [BenchmarkCategory("Array")] - [Benchmark] - public bool Hyperlinq_Span() - => array.AsSpan().Any(); - - [BenchmarkCategory("Array")] - [Benchmark] - public bool Hyperlinq_Memory() - => memory.AsValueEnumerable().Any(); + => array.AsValueEnumerable().Any(); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public bool Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Any(); [BenchmarkCategory("Collection_Value")] [Benchmark] public bool Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Any(); [BenchmarkCategory("List_Value")] @@ -95,7 +84,7 @@ public bool Hyperlinq_List_Value() [Benchmark] public ValueTask Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) + .AsAsyncValueEnumerable() .AnyAsync(); [BenchmarkCategory("Enumerable_Reference")] diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyPredicateBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyPredicateBenchmarks.cs index c2d2c288b..2debd4f30 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyPredicateBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/AnyPredicateBenchmarks.cs @@ -1,6 +1,5 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using System; using System.Linq; using System.Threading.Tasks; @@ -13,75 +12,65 @@ public class AnyPredicateBenchmarks: RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public bool Linq_Array() - => Enumerable.Any(array, _ => false); + => array.Any(_ => false); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public bool Linq_Enumerable_Value() - => Enumerable.Any(enumerableValue, _ => false); + => enumerableValue.Any(_ => false); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public bool Linq_Collection_Value() - => Enumerable.Any(collectionValue, _ => false); + => collectionValue.Any(_ => false); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public bool Linq_List_Value() - => Enumerable.Any(listValue, _ => false); + => listValue.Any(_ => false); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.AnyAsync(asyncEnumerableValue, _ => false); + => asyncEnumerableValue.AnyAsync(_ => false); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public bool Linq_Enumerable_Reference() - => Enumerable.Any(enumerableReference, _ => false); + => enumerableReference.Any(_ => false); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public bool Linq_Collection_Reference() - => Enumerable.Any(collectionReference, _ => false); + => collectionReference.Any(_ => false); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public bool Linq_List_Reference() - => Enumerable.Any(listReference, _ => false); + => listReference.Any(_ => false); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.AnyAsync(asyncEnumerableReference, _ => false); + => asyncEnumerableReference.AnyAsync(_ => false); // --------------------------------------------------------------------- [BenchmarkCategory("Array")] [Benchmark] public bool Hyperlinq_Array() - => array.Any(_ => false); - - [BenchmarkCategory("Array")] - [Benchmark] - public bool Hyperlinq_Span() - => array.AsSpan().Any(_ => false); - - [BenchmarkCategory("Array")] - [Benchmark] - public bool Hyperlinq_Memory() - => memory.AsValueEnumerable().Any(_ => false); + => array.AsValueEnumerable().Any(_ => false); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public bool Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Any(_ => false); [BenchmarkCategory("Collection_Value")] [Benchmark] public bool Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Any(_ => false); [BenchmarkCategory("List_Value")] @@ -95,8 +84,8 @@ public bool Hyperlinq_List_Value() [Benchmark] public ValueTask Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - .AnyAsync((item, _) => new ValueTask((item & 0x01) == 0)); + .AsAsyncValueEnumerable() + .AnyAsync((_, _) => default); [BenchmarkCategory("Enumerable_Reference")] [Benchmark] @@ -124,6 +113,6 @@ public bool Hyperlinq_List_Reference() public ValueTask Hyperlinq_AsyncEnumerable_Reference() => asyncEnumerableReference .AsAsyncValueEnumerable() - .AnyAsync((item, _) => new ValueTask((item & 0x01) == 0)); + .AnyAsync((_, _) => default); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ArrayIterationBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ArrayIterationBenchmarks.cs index 748e6e068..b74b4255f 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ArrayIterationBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ArrayIterationBenchmarks.cs @@ -1,27 +1,25 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Jobs; using System; -using System.Collections.Generic; +using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace NetFabric.Hyperlinq.Benchmarks.Benchmarks { - [SimpleJob(RuntimeMoniker.NetCoreApp50)] public class ArrayIterationBenchmarks { const int seed = 2982; - int[] array; - ReadOnlyMemory memory; + int[]? array; ArraySegment segment; - [Params(10_000_000)] + [Params(1_000_000)] public int Count { get; set; } [GlobalSetup] public void GlobalSetup() { array = Utils.GetRandomValues(seed, Count); - memory = Utils.GetRandomValues(seed, Count).AsMemory(); segment = new ArraySegment(Utils.GetRandomValues(seed, Count)); } @@ -29,168 +27,164 @@ public void GlobalSetup() public int Foreach() { var sum = 0; - foreach (var item in array) + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (var item in array!) sum += item; return sum; } - + [Benchmark] public int For() { - var source = array; + var source = array!; var sum = 0; - for (var index = 0; index < source.Length; index++) + // ReSharper disable once ForCanBeConvertedToForeach + // ReSharper disable once LoopCanBeConvertedToQuery + for (var index = 0; index <= source.Length - 1; index++) { - var item = array[index]; + var item = source[index]; sum += item; } return sum; } - + [Benchmark] public unsafe int For_Unsafe() { - var end = array.Length; + var len = array!.Length - 1; var sum = 0; fixed (int* source = array) { - for (var index = 0; index < end; index++) + for (var index = 0; index <= len; index++) { - var item = array[index]; + var item = source[index]; sum += item; } } return sum; } - + [Benchmark] public int ForAdamczewski() { - var source = array; - var len = array.Length; + var source = array!; var sum1 = 0; var sum2 = 0; - for (var index = 0; index < len; index += 2) + for (var index = 0; index <= source.Length - 2; index += 2) { - long i1 = index + 0; - long i2 = index + 1; - var c = source[i1]; - var d = source[i2]; + var c = source[index + 0]; + var d = source[index + 1]; sum1 += c; sum2 += d; } + if ((source.Length & 0x01) != 0) + { + sum1 += source[source.Length - 1]; + } return sum1 + sum2; } - + [Benchmark] public unsafe int ForAdamczewskiUnsafe() { fixed (int* source = array) { - var len = array.Length; + var len = array!.Length - 2; var sum1 = 0; var sum2 = 0; - for (var index = 0; index < len; index += 2) + for (var index = 0; index <= len; index += 2) { - long i1 = index + 0; - long i2 = index + 1; - var c = source[i1]; - var d = source[i2]; - + var c = source[index + 0]; + var d = source[index + 1]; + sum1 += c; sum2 += d; } + if ((array.Length & 0x01) != 0) + { + sum1 += source[array!.Length - 1]; + } return sum1 + sum2; } } - + [Benchmark] public int Span() { var source = array.AsSpan(); var sum = 0; - for (var index = 0; index < source.Length; index++) - { - var item = source[index]; - sum += item; - } - return sum; - } - - [Benchmark] - public int Memory() - { - var source = memory.Span; - var sum = 0; - for (var index = 0; index < source.Length; index++) - { - var item = source[index]; + foreach (var item in source) sum += item; - } return sum; } - + [Benchmark] public int ArraySegment_Foreach() { var sum = 0; + // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator foreach (var item in segment) sum += item; return sum; } - + [Benchmark] public int ArraySegment_For() { - var source = segment.Array; - var start = segment.Offset; - var end = start + segment.Count; + var source = segment; var sum = 0; - for (var index = start; index < end; index++) + // ReSharper disable once LoopCanBeConvertedToQuery + // ReSharper disable once ForCanBeConvertedToForeach + for (var index = 0; index < source.Count; index++) { var item = source[index]; sum += item; } return sum; } - + [Benchmark] - public int ArraySegment_Wrapper_Foreach() + public int ArraySegment_AsSpan() { - var source = new ArraySegmentWrapper(segment); var sum = 0; - foreach (var item in source) + // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator + foreach (var item in segment.AsSpan()) sum += item; return sum; } + + [Benchmark] + public int ArraySegment_AsArray() + { + var source = segment.Array!; + var end = segment.Offset + segment.Count; + var sum = 0; + for (var index = segment.Offset; index < end; index++) + sum += source[index]; + return sum; + } - readonly struct ArraySegmentWrapper + [Benchmark] + public int Vector() { - readonly ArraySegment source; + var source = array!; + var sum = 0; + var vectors = MemoryMarshal.Cast>(source); + var vectorSum = Vector.Zero; - public ArraySegmentWrapper(in ArraySegment source) - => this.source = source; + foreach (var vector in vectors) + vectorSum += vector; - public Enumerator GetEnumerator() - => new(source); + for (var index = 0; index < Vector.Count; index++) + sum += vectorSum[index]; - public struct Enumerator + for (var index = source.Length - (source.Length % Vector.Count); index < source.Length; index++) { - readonly TSource[] array; - readonly int end; - int current; - - public Enumerator(in ArraySegment source) - => (array, end, current) = (source.Array!, source.Offset + source.Count - 1, -1); - - public TSource Current - => array[current]; - - public bool MoveNext() - => ++current <= end; + var item = source[index]; + sum += item; } - } - + return sum; + } } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ArrayToArrayBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ArrayToArrayBenchmarks.cs new file mode 100644 index 000000000..5182ff7db --- /dev/null +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ArrayToArrayBenchmarks.cs @@ -0,0 +1,43 @@ +using BenchmarkDotNet.Attributes; +using System; +using System.Collections.Generic; + +namespace NetFabric.Hyperlinq.Benchmarks.Benchmarks +{ + public class ArrayToArrayBenchmarks + { + const int seed = 2982; + int[]? array; + + [Params(10, 100, 1000)] + public int Count { get; set; } + + [GlobalSetup] + public void GlobalSetup() + => array = Utils.GetRandomValues(seed, Count); + + [Benchmark(Baseline = true)] + public int[] ArrayClone() + => (int[])array!.Clone(); + + [Benchmark] + public int[] SpanToArray() + => array.AsSpan().ToArray(); + + [Benchmark] + public int[] SpanCopyTo() + { + var result = GC.AllocateUninitializedArray(Count); + array.AsSpan().CopyTo(result); + return result; + } + + [Benchmark] + public int[] CollectionCopyTo() + { + var result = GC.AllocateUninitializedArray(Count); + ((ICollection)array!).CopyTo(result, 0); + return result; + } + } +} diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsBenchmarks.cs index 4a9ce38e4..acd3ad7e4 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsBenchmarks.cs @@ -1,6 +1,5 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using System; using System.Linq; using System.Threading.Tasks; @@ -13,47 +12,47 @@ public class ContainsBenchmarks : SequentialBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public bool Linq_Array() - => Enumerable.Contains(array, Count - 1); - - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark(Baseline = true)] - //public bool Linq_Enumerable_Value() - // => Enumerable.Contains(enumerableValue, Count - 1); - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark(Baseline = true)] - //public bool Linq_Collection_Value() - // => Enumerable.Contains(collectionValue, Count - 1); - - //[BenchmarkCategory("List_Value")] - //[Benchmark(Baseline = true)] - //public bool Linq_List_Value() - // => Enumerable.Contains(listValue, Count - 1); - - //[BenchmarkCategory("AsyncEnumerable_Value")] - //[Benchmark(Baseline = true)] - //public ValueTask Linq_AsyncEnumerable_Value() - // => AsyncEnumerable.ContainsAsync(asyncEnumerableValue, Count - 1); - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark(Baseline = true)] - //public bool Linq_Enumerable_Reference() - // => Enumerable.Contains(enumerableReference, Count - 1); - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark(Baseline = true)] - //public bool Linq_Collection_Reference() - // => Enumerable.Contains(collectionReference, Count - 1); - - //[BenchmarkCategory("List_Reference")] - //[Benchmark(Baseline = true)] - //public bool Linq_List_Reference() - // => Enumerable.Contains(listReference, Count - 1); - - //[BenchmarkCategory("AsyncEnumerable_Reference")] - //[Benchmark(Baseline = true)] - //public ValueTask Linq_AsyncEnumerable_Reference() - // => AsyncEnumerable.ContainsAsync(asyncEnumerableReference, Count - 1); + => array.Contains(Count - 1); + + [BenchmarkCategory("Enumerable_Value")] + [Benchmark(Baseline = true)] + public bool Linq_Enumerable_Value() + => enumerableValue.Contains(Count - 1); + + [BenchmarkCategory("Collection_Value")] + [Benchmark(Baseline = true)] + public bool Linq_Collection_Value() + => collectionValue.Contains(Count - 1); + + [BenchmarkCategory("List_Value")] + [Benchmark(Baseline = true)] + public bool Linq_List_Value() + => Enumerable.Contains(listValue, Count - 1); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Value() + => asyncEnumerableValue.ContainsAsync(Count - 1); + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark(Baseline = true)] + public bool Linq_Enumerable_Reference() + => enumerableReference.Contains(Count - 1); + + [BenchmarkCategory("Collection_Reference")] + [Benchmark(Baseline = true)] + public bool Linq_Collection_Reference() + => collectionReference.Contains(Count - 1); + + [BenchmarkCategory("List_Reference")] + [Benchmark(Baseline = true)] + public bool Linq_List_Reference() + => listReference.Contains(Count - 1); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Reference() + => asyncEnumerableReference.ContainsAsync(Count - 1); // --------------------------------------------------------------------- @@ -64,57 +63,61 @@ public bool Hyperlinq_Array() [BenchmarkCategory("Array")] [Benchmark] - public bool Hyperlinq_Span() - => array.AsSpan().Contains(Count - 1); + public bool Hyperlinq_Array_SIMD() + => array.AsValueEnumerable().ContainsVector(Count - 1); - [BenchmarkCategory("Array")] + [BenchmarkCategory("Enumerable_Value")] + [Benchmark] + public bool Hyperlinq_Enumerable_Value() + => enumerableValue.AsValueEnumerable() + .Contains(Count - 1); + + [BenchmarkCategory("Collection_Value")] + [Benchmark] + public bool Hyperlinq_Collection_Value() + => collectionValue.AsValueEnumerable() + .Contains(Count - 1); + + [BenchmarkCategory("List_Value")] + [Benchmark] + public bool Hyperlinq_List_Value() + => listValue + .AsValueEnumerable() + .Contains(Count - 1); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public ValueTask Hyperlinq_AsyncEnumerable_Value() + => asyncEnumerableValue + .AsAsyncValueEnumerable() + .ContainsAsync(Count - 1); + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark] + public bool Hyperlinq_Enumerable_Reference() + => enumerableReference + .AsValueEnumerable() + .Contains(Count - 1); + + [BenchmarkCategory("Collection_Reference")] + [Benchmark] + public bool Hyperlinq_Collection_Reference() + => collectionReference + .AsValueEnumerable() + .Contains(Count - 1); + + [BenchmarkCategory("List_Reference")] + [Benchmark] + public bool Hyperlinq_List_Reference() + => listReference + .AsValueEnumerable() + .Contains(Count - 1); + + [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark] - public bool Hyperlinq_Span_SIMD() - => array.AsSpan().ContainsVector(Count - 1); - - //[BenchmarkCategory("Array")] - //[Benchmark] - //public bool Hyperlinq_Memory() - // => memory.AsValueEnumerable().Contains(Count - 1); - - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark] - //public bool Hyperlinq_Enumerable_Value() - // => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) - // .Contains(Count - 1); - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark] - //public bool Hyperlinq_Collection_Value() - // => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) - // .Contains(Count - 1); - - //[BenchmarkCategory("List_Value")] - //[Benchmark] - //public bool Hyperlinq_List_Value() - // => listValue - // .AsValueEnumerable() - // .Contains(Count - 1); - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark] - //public bool Hyperlinq_Enumerable_Reference() - // => enumerableReference - // .AsValueEnumerable() - // .Contains(Count - 1); - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark] - //public bool Hyperlinq_Collection_Reference() - // => collectionReference - // .AsValueEnumerable() - // .Contains(Count - 1); - - //[BenchmarkCategory("List_Reference")] - //[Benchmark] - //public bool Hyperlinq_List_Reference() - // => listReference - // .AsValueEnumerable() - // .Contains(Count - 1); + public ValueTask Hyperlinq_AsyncEnumerable_Reference() + => asyncEnumerableReference + .AsAsyncValueEnumerable() + .ContainsAsync(Count - 1); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsComparerBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsComparerBenchmarks.cs index 3b6058aa3..61e6bfd9e 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsComparerBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ContainsComparerBenchmarks.cs @@ -1,6 +1,5 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -14,75 +13,65 @@ public class ContainsComparerBenchmarks: SequentialBenchmarksBase, IEqualityComp [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public bool Linq_Array() - => Enumerable.Contains(array, Count - 1, this); + => array.Contains(Count - 1, this); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public bool Linq_Enumerable_Value() - => Enumerable.Contains(enumerableValue, Count - 1, this); + => enumerableValue.Contains(Count - 1, this); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public bool Linq_Collection_Value() - => Enumerable.Contains(collectionValue, Count - 1, this); + => collectionValue.Contains(Count - 1, this); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public bool Linq_List_Value() - => Enumerable.Contains(listValue, Count - 1, this); + => listValue.Contains(Count - 1, this); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.ContainsAsync(asyncEnumerableValue, Count - 1, this); + => asyncEnumerableValue.ContainsAsync(Count - 1, this); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public bool Linq_Enumerable_Reference() - => Enumerable.Contains(enumerableReference, Count - 1, this); + => enumerableReference.Contains(Count - 1, this); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public bool Linq_Collection_Reference() - => Enumerable.Contains(collectionReference, Count - 1, this); + => collectionReference.Contains(Count - 1, this); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public bool Linq_List_Reference() - => Enumerable.Contains(listReference, Count - 1, this); + => listReference.Contains(Count - 1, this); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.ContainsAsync(asyncEnumerableReference, Count - 1, this); + => asyncEnumerableReference.ContainsAsync(Count - 1, this); // --------------------------------------------------------------------- [BenchmarkCategory("Array")] [Benchmark] public bool Hyperlinq_Array() - => array.Contains(Count - 1, this); - - [BenchmarkCategory("Array")] - [Benchmark] - public bool Hyperlinq_Span() - => array.AsSpan().Contains(Count - 1, this); - - [BenchmarkCategory("Array")] - [Benchmark] - public bool Hyperlinq_Memory() - => memory.AsValueEnumerable().Contains(Count - 1, this); + => array.AsValueEnumerable().Contains(Count - 1, this); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public bool Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Contains(Count - 1, this); [BenchmarkCategory("Collection_Value")] [Benchmark] public bool Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Contains(Count - 1, this); [BenchmarkCategory("List_Value")] @@ -92,6 +81,13 @@ public bool Hyperlinq_List_Value() .AsValueEnumerable() .Contains(Count - 1, this); + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public ValueTask Hyperlinq_AsyncEnumerable_Value() + => asyncEnumerableValue + .AsAsyncValueEnumerable() + .ContainsAsync(Count - 1, this); + [BenchmarkCategory("Enumerable_Reference")] [Benchmark] public bool Hyperlinq_Enumerable_Reference() @@ -113,6 +109,13 @@ public bool Hyperlinq_List_Reference() .AsValueEnumerable() .Contains(Count - 1, this); + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark] + public ValueTask Hyperlinq_AsyncEnumerable_Reference() + => asyncEnumerableReference + .AsAsyncValueEnumerable() + .ContainsAsync(Count - 1, this); + // --------------------------------------------------------------------- public bool Equals(int x, int y) diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/CountBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/CountBenchmarks.cs index 64c86f155..42cafd441 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/CountBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/CountBenchmarks.cs @@ -1,7 +1,6 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using StructLinq; -using System; using System.Linq; using System.Threading.Tasks; @@ -14,47 +13,47 @@ public class CountBenchmarks : RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() - => Enumerable.Count(array); + => array.Count(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Value() - => Enumerable.Count(enumerableValue); + => enumerableValue.Count(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int Linq_Collection_Value() - => Enumerable.Count(collectionValue); + => collectionValue.Count(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int Linq_List_Value() - => Enumerable.Count(listValue); + => listValue.Count(); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.CountAsync(asyncEnumerableValue); + => asyncEnumerableValue.CountAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Reference() - => Enumerable.Count(enumerableReference); + => enumerableReference.Count(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int Linq_Collection_Reference() - => Enumerable.Count(collectionReference); + => collectionReference.Count(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int Linq_List_Reference() - => Enumerable.Count(listReference); + => listReference.Count(); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.CountAsync(asyncEnumerableReference); + => asyncEnumerableReference.CountAsync(); // --------------------------------------------------------------------- @@ -112,28 +111,22 @@ public int StructLinq_List_Reference() [BenchmarkCategory("Array")] [Benchmark] public int Hyperlinq_Array() - => array.Count(); - - [BenchmarkCategory("Array")] - [Benchmark] - public int Hyperlinq_Span() - => array.AsSpan().Count(); - - [BenchmarkCategory("Array")] - [Benchmark] - public int Hyperlinq_Memory() - => memory.AsValueEnumerable().Count(); + => array + .AsValueEnumerable() + .Count(); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public int Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue + .AsValueEnumerable() .Count(); [BenchmarkCategory("Collection_Value")] [Benchmark] public int Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue + .AsValueEnumerable() .Count(); [BenchmarkCategory("List_Value")] @@ -147,7 +140,7 @@ public int Hyperlinq_List_Value() [Benchmark] public ValueTask Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) + .AsAsyncValueEnumerable() .CountAsync(); [BenchmarkCategory("Enumerable_Reference")] diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/DistinctBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/DistinctBenchmarks.cs index 6bffda85d..ede1a3a8d 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/DistinctBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/DistinctBenchmarks.cs @@ -4,6 +4,8 @@ using System; using System.Linq; using System.Threading.Tasks; +// ReSharper disable ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator +// ReSharper disable LoopCanBeConvertedToQuery namespace NetFabric.Hyperlinq.Benchmarks { @@ -16,7 +18,7 @@ public class DistinctBenchmarks : RandomBenchmarksBase public int Linq_Array() { var sum = 0; - foreach (var item in Enumerable.Distinct(array)) + foreach (var item in array.Distinct()) sum += item; return sum; } @@ -26,7 +28,7 @@ public int Linq_Array() public int Linq_Enumerable_Value() { var sum = 0; - foreach (var item in Enumerable.Distinct(enumerableValue)) + foreach (var item in enumerableValue.Distinct()) sum += item; return sum; } @@ -36,7 +38,7 @@ public int Linq_Enumerable_Value() public int Linq_Collection_Value() { var sum = 0; - foreach (var item in Enumerable.Distinct(collectionValue)) + foreach (var item in collectionValue.Distinct()) sum += item; return sum; } @@ -46,17 +48,17 @@ public int Linq_Collection_Value() public int Linq_List_Value() { var sum = 0; - foreach (var item in Enumerable.Distinct(listValue)) + foreach (var item in listValue.Distinct()) sum += item; return sum; } [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] - public async Task Linq_AsyncEnumerable_Value() + public async ValueTask Linq_AsyncEnumerable_Value() { var sum = 0; - await foreach (var item in AsyncEnumerable.Distinct(asyncEnumerableValue)) + await foreach (var item in asyncEnumerableValue.Distinct()) sum += item; return sum; } @@ -66,7 +68,7 @@ await foreach (var item in AsyncEnumerable.Distinct(asyncEnumerableValue)) public int Linq_Enumerable_Reference() { var sum = 0; - foreach (var item in Enumerable.Distinct(enumerableReference)) + foreach (var item in enumerableReference.Distinct()) sum += item; return sum; } @@ -76,7 +78,7 @@ public int Linq_Enumerable_Reference() public int Linq_Collection_Reference() { var sum = 0; - foreach (var item in Enumerable.Distinct(collectionReference)) + foreach (var item in collectionReference.Distinct()) sum += item; return sum; } @@ -86,17 +88,17 @@ public int Linq_Collection_Reference() public int Linq_List_Reference() { var sum = 0; - foreach (var item in Enumerable.Distinct(listReference)) + foreach (var item in listReference.Distinct()) sum += item; return sum; } [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] - public async Task Linq_AsyncEnumerable_Reference() + public async ValueTask Linq_AsyncEnumerable_Reference() { var sum = 0; - await foreach (var item in AsyncEnumerable.Distinct(asyncEnumerableReference)) + await foreach (var item in asyncEnumerableReference.Distinct()) sum += item; return sum; } @@ -108,7 +110,7 @@ await foreach (var item in AsyncEnumerable.Distinct(asyncEnumerableReference)) public int StructLinq_Array() { var sum = 0; - foreach (var item in array.Distinct(x => x)) + foreach (var item in array.ToStructEnumerable().Distinct(x => x)) sum += item; return sum; } @@ -180,7 +182,7 @@ public int StructLinq_List_Reference() public int Hyperlinq_Array() { var sum = 0; - foreach (var item in array.Distinct()) + foreach (var item in array.AsValueEnumerable().Distinct()) sum += item; return sum; } @@ -190,7 +192,7 @@ public int Hyperlinq_Array() public int Hyperlinq_Span() { var sum = 0; - foreach (ref readonly var item in array.AsSpan().Distinct()) + foreach (ref readonly var item in array.AsSpan().AsValueEnumerable().Distinct()) sum += item; return sum; } @@ -210,7 +212,7 @@ public int Hyperlinq_Memory() public int Hyperlinq_Enumerable_Value() { var sum = 0; - foreach (var item in EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()).Distinct()) + foreach (var item in enumerableValue.AsValueEnumerable().Distinct()) sum += item; return sum; } @@ -220,7 +222,7 @@ public int Hyperlinq_Enumerable_Value() public int Hyperlinq_Collection_Value() { var sum = 0; - foreach (var item in ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()).Distinct()) + foreach (var item in collectionValue.AsValueEnumerable().Distinct()) sum += item; return sum; } @@ -237,10 +239,12 @@ public int Hyperlinq_List_Value() [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark] - public async Task Hyperlinq_AsyncEnumerable_Value() + public async ValueTask Hyperlinq_AsyncEnumerable_Value() { var sum = 0; - await foreach (var item in asyncEnumerableValue.AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)).Distinct()) + await foreach (var item in asyncEnumerableValue + .AsAsyncValueEnumerable() + .Distinct()) sum += item; return sum; } @@ -277,7 +281,7 @@ public int Hyperlinq_List_Reference() [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark] - public async Task Hyperlinq_AsyncEnumerable_Reference() + public async ValueTask Hyperlinq_AsyncEnumerable_Reference() { var sum = 0; await foreach (var item in asyncEnumerableReference.AsAsyncValueEnumerable().Distinct()) diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ElementAtBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ElementAtBenchmarks.cs index 6a12cf57f..1d525448f 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ElementAtBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ElementAtBenchmarks.cs @@ -1,6 +1,5 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using System; using System.Linq; using System.Threading.Tasks; @@ -13,75 +12,69 @@ public class ElementAtBenchmarks: SequentialBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() - => Enumerable.ElementAt(array, Count - 1); + => array.ElementAt(Count - 1); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Value() - => Enumerable.ElementAt(enumerableValue, Count - 1); + => enumerableValue.ElementAt(Count - 1); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int Linq_Collection_Value() - => Enumerable.ElementAt(collectionValue, Count - 1); + => collectionValue.ElementAt(Count - 1); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int Linq_List_Value() - => Enumerable.ElementAt(listValue, Count - 1); + => listValue.ElementAt(Count - 1); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.ElementAtAsync(asyncEnumerableValue, Count - 1); + => asyncEnumerableValue.ElementAtAsync(Count - 1); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Reference() - => Enumerable.ElementAt(enumerableReference, Count - 1); + => enumerableReference.ElementAt(Count - 1); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int Linq_Collection_Reference() - => Enumerable.ElementAt(collectionReference, Count - 1); + => collectionReference.ElementAt(Count - 1); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int Linq_List_Reference() - => Enumerable.ElementAt(listReference, Count - 1); + => listReference.ElementAt(Count - 1); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.ElementAtAsync(asyncEnumerableReference, Count - 1); + => asyncEnumerableReference.ElementAtAsync(Count - 1); // --------------------------------------------------------------------- [BenchmarkCategory("Array")] [Benchmark] public Option Hyperlinq_Array() - => array.AsValueEnumerable().ElementAt(Count - 1); - - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Span() - => array.AsSpan().ElementAt(Count - 1); - - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Memory() - => memory.AsValueEnumerable().ElementAt(Count - 1); + => array + .AsValueEnumerable() + .ElementAt(Count - 1); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public Option Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue + .AsValueEnumerable() .ElementAt(Count - 1); [BenchmarkCategory("Collection_Value")] [Benchmark] public Option Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue + .AsValueEnumerable() .ElementAt(Count - 1); [BenchmarkCategory("List_Value")] @@ -91,6 +84,13 @@ public Option Hyperlinq_List_Value() .AsValueEnumerable() .ElementAt(Count - 1); + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public ValueTask> Hyperlinq_AsyncEnumerable_Value() + => asyncEnumerableValue + .AsAsyncValueEnumerable() + .ElementAtAsync(Count - 1); + [BenchmarkCategory("Enumerable_Reference")] [Benchmark] public Option Hyperlinq_Enumerable_Reference() @@ -111,5 +111,12 @@ public Option Hyperlinq_List_Reference() => listReference .AsValueEnumerable() .ElementAt(Count - 1); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark] + public ValueTask> Hyperlinq_AsyncEnumerable_Reference() + => asyncEnumerableReference + .AsAsyncValueEnumerable() + .ElementAtAsync(Count - 1); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/EmptyBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/EmptyBenchmarks.cs index 786482170..cba2268f2 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/EmptyBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/EmptyBenchmarks.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using StructLinq; namespace NetFabric.Hyperlinq.Benchmarks { diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/FirstBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/FirstBenchmarks.cs index a414a24c2..8c31d799d 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/FirstBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/FirstBenchmarks.cs @@ -1,6 +1,5 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using System; using System.Linq; using System.Threading.Tasks; @@ -8,80 +7,74 @@ namespace NetFabric.Hyperlinq.Benchmarks { [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] [CategoriesColumn] - public class FirstBenchmarks: RandomBenchmarksBase + public class FirstBenchmarks: SequentialBenchmarksBase { [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() - => Enumerable.First(array); + => array.First(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Value() - => Enumerable.First(enumerableValue); + => enumerableValue.First(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int Linq_Collection_Value() - => Enumerable.First(collectionValue); + => collectionValue.First(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int Linq_List_Value() - => Enumerable.First(listValue); + => listValue.First(); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.FirstAsync(asyncEnumerableValue); + => asyncEnumerableValue.FirstAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Reference() - => Enumerable.First(enumerableReference); + => enumerableReference.First(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int Linq_Collection_Reference() - => Enumerable.First(collectionReference); + => collectionReference.First(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int Linq_List_Reference() - => Enumerable.First(listReference); + => listReference.First(); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.FirstAsync(asyncEnumerableReference); + => asyncEnumerableReference.FirstAsync(); // --------------------------------------------------------------------- [BenchmarkCategory("Array")] [Benchmark] public Option Hyperlinq_Array() - => array.AsValueEnumerable().First(); - - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Span() - => array.AsSpan().First(); - - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Memory() - => memory.AsValueEnumerable().First(); + => array + .AsValueEnumerable() + .First(); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public Option Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue + .AsValueEnumerable() .First(); [BenchmarkCategory("Collection_Value")] [Benchmark] public Option Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue + .AsValueEnumerable() .First(); [BenchmarkCategory("List_Value")] @@ -91,6 +84,13 @@ public Option Hyperlinq_List_Value() .AsValueEnumerable() .First(); + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public ValueTask> Hyperlinq_AsyncEnumerable_Value() + => asyncEnumerableValue + .AsAsyncValueEnumerable() + .FirstAsync(); + [BenchmarkCategory("Enumerable_Reference")] [Benchmark] public Option Hyperlinq_Enumerable_Reference() @@ -111,5 +111,12 @@ public Option Hyperlinq_List_Reference() => listReference .AsValueEnumerable() .First(); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark] + public ValueTask> Hyperlinq_AsyncEnumerable_Reference() + => asyncEnumerableReference + .AsAsyncValueEnumerable() + .FirstAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/IterationBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/IterationBenchmarks.cs deleted file mode 100644 index 43334c0d2..000000000 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/IterationBenchmarks.cs +++ /dev/null @@ -1,72 +0,0 @@ -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Jobs; - -namespace NetFabric.Hyperlinq.Benchmarks.Benchmarks -{ - [SimpleJob(RuntimeMoniker.NetCoreApp50)] - public class IterationBenchmarks - { - [Params(100_000_000)] - public int Count { get; set; } - - [Benchmark(Baseline = true)] - public int LT() - { - var sum = 0; - foreach (var item in new EnumerableLT(Count)) - sum += item; - return sum; - } - - [Benchmark] - public int LTE() - { - var sum = 0; - foreach (var item in new EnumerableLTE(Count)) - sum += item; - return sum; - } - - readonly struct EnumerableLT - { - readonly int count; - - public EnumerableLT(int count) => this.count = count; - - public Enumerator GetEnumerator() => new(count); - - public struct Enumerator - { - int current; - readonly int end; - - public Enumerator(int count) => (current, end) = (-1, count); - - public int Current => 1; - - public bool MoveNext() => ++current < end; - } - } - - readonly struct EnumerableLTE - { - readonly int count; - - public EnumerableLTE(int count) => this.count = count; - - public Enumerator GetEnumerator() => new(count); - - public struct Enumerator - { - int current; - readonly int end; - - public Enumerator(int count) => (current, end) = (-1, count - 1); - - public int Current => 1; - - public bool MoveNext() => ++current <= end; - } - } - } -} diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ListIterationBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ListIterationBenchmarks.cs new file mode 100644 index 000000000..d3d495f81 --- /dev/null +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ListIterationBenchmarks.cs @@ -0,0 +1,92 @@ +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Jobs; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +// ReSharper disable ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator +// ReSharper disable ForCanBeConvertedToForeach + +namespace NetFabric.Hyperlinq.Benchmarks.Benchmarks +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + [CategoriesColumn] + public class ListIterationBenchmarks + { + const int seed = 2982; + List list; + ImmutableList immutableList; + + [Params(1_000_000)] + public int Count { get; set; } + + [GlobalSetup] + public void GlobalSetup() + { + var source = Utils.GetRandomValues(seed, Count); + list = new List(source); + immutableList = ImmutableList.Create(source); + } + + [BenchmarkCategory("List")] + [Benchmark(Baseline = true)] + public int List_Enumerable() + { + var sum = 0; + foreach (var item in list) + sum += item; + return sum; + } + + [BenchmarkCategory("List")] + [Benchmark] + public int List_Indexer() + { + var source = list; + var sum = 0; + for (var index = 0; index < source.Count; index++) + { + var item = source[index]; + sum += item; + } + return sum; + } + + [BenchmarkCategory("List")] + [Benchmark] + public int List_Span() + { + var sum = 0; + foreach (var item in CollectionsMarshal.AsSpan(list)) + sum += item; + return sum; + } + + + [BenchmarkCategory("ImmutableList")] + [Benchmark(Baseline = true)] + public int ImmutableList_Enumerable() + { + var sum = 0; + foreach (var item in immutableList) + sum += item; + return sum; + } + + [BenchmarkCategory("ImmutableList")] + [Benchmark] + public int ImmutableList_Indexer() + { + var source = immutableList; + var sum = 0; + for (var index = 0; index < source.Count; index++) + { + var item = source[index]; + sum += item; + } + return sum; + } + } +} diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/RangeBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/RangeBenchmarks.cs index 067b5c9cc..33735309d 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/RangeBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/RangeBenchmarks.cs @@ -1,11 +1,10 @@ -using System; -using System.Collections; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using StructLinq; +// ReSharper disable ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator +// ReSharper disable LoopCanBeConvertedToQuery namespace NetFabric.Hyperlinq.Benchmarks { diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ReadOnlyFieldsBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ReadOnlyFieldsBenchmarks.cs new file mode 100644 index 000000000..7cdac5588 --- /dev/null +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ReadOnlyFieldsBenchmarks.cs @@ -0,0 +1,121 @@ +using BenchmarkDotNet.Attributes; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq.Benchmarks.Benchmarks +{ + public class ReadOnlyFieldsBenchmarks + { + const int seed = 2982; + int[]? array; + + [Params(1_000)] + public int Count { get; set; } + + [GlobalSetup] + public void GlobalSetup() + => array = Utils.GetRandomValues(seed, Count); + + [Benchmark(Baseline = true)] + public int Baseline() + { + var enumerator = new Enumerator(array!); + var sum = 0; + while (enumerator.MoveNext()) + sum += enumerator.Current; + return sum; + } + + [Benchmark] + public int ReadOnlyCurrent() + { + var enumerator = new ReadOnlyCurrentEnumerator(array!); + var sum = 0; + while (enumerator.MoveNext()) + sum += enumerator.Current; + return sum; + } + + [Benchmark] + public int ReadOnlyField() + { + var enumerator = new ReadOnlyFieldEnumerator(array!); + var sum = 0; + while (enumerator.MoveNext()) + sum += enumerator.Current; + return sum; + } + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + { + // ReSharper disable once FieldCanBeMadeReadOnly.Local + TSource[] source; + int index; + + public Enumerator(TSource[] source) + { + this.source = source; + index = -1; + } + + public TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + => ++index < source.Length; + } + + [StructLayout(LayoutKind.Auto)] + public struct ReadOnlyCurrentEnumerator + { + // ReSharper disable once FieldCanBeMadeReadOnly.Local + TSource[] source; + int index; + + public ReadOnlyCurrentEnumerator(TSource[] source) + { + this.source = source; + index = -1; + } + + public readonly TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + => ++index < source.Length; + } + + [StructLayout(LayoutKind.Auto)] + public struct ReadOnlyFieldEnumerator + { + readonly TSource[] source; + int index; + + public ReadOnlyFieldEnumerator(TSource[] source) + { + this.source = source; + index = -1; + } + + public readonly TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + => ++index < source.Length; + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/RepeatBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/RepeatBenchmarks.cs index f37b280ca..c54915bf0 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/RepeatBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/RepeatBenchmarks.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ReturnBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ReturnBenchmarks.cs index 1cafda77e..9c4c7d272 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ReturnBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ReturnBenchmarks.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using StructLinq; namespace NetFabric.Hyperlinq.Benchmarks { diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectBenchmarks.cs index ff7057fea..2afd7aac4 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectBenchmarks.cs @@ -2,6 +2,8 @@ using BenchmarkDotNet.Configs; using StructLinq; using System; +using System.Linq; +using System.Threading.Tasks; namespace NetFabric.Hyperlinq.Benchmarks { @@ -14,70 +16,90 @@ public class SelectBenchmarks : RandomBenchmarksBase public int Linq_Array() { var sum = 0; - foreach (var item in System.Linq.Enumerable.Select(array, item => item)) + foreach (var item in array.Select(item => item)) sum += item; return sum; } - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark(Baseline = true)] - //public int Linq_Enumerable_Value() - //{ - // var sum = 0; - // foreach (var item in System.Linq.Enumerable.Select(enumerableValue, item => item)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark(Baseline = true)] - //public int Linq_Collection_Value() - //{ - // var sum = 0; - // foreach (var item in System.Linq.Enumerable.Select(collectionValue, item => item)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("List_Value")] - //[Benchmark(Baseline = true)] - //public int Linq_List_Value() - //{ - // var sum = 0; - // foreach (var item in System.Linq.Enumerable.Select(listValue, item => item)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark(Baseline = true)] - //public int Linq_Enumerable_Reference() - //{ - // var sum = 0; - // foreach (var item in System.Linq.Enumerable.Select(enumerableReference, item => item)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark(Baseline = true)] - //public int Linq_Collection_Reference() - //{ - // var sum = 0; - // foreach (var item in System.Linq.Enumerable.Select(collectionReference, item => item)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("List_Reference")] - //[Benchmark(Baseline = true)] - //public int Linq_List_Reference() - //{ - // var sum = 0; - // foreach (var item in System.Linq.Enumerable.Select(listReference, item => item)) - // sum += item; - // return sum; - //} + [BenchmarkCategory("Enumerable_Value")] + [Benchmark(Baseline = true)] + public int Linq_Enumerable_Value() + { + var sum = 0; + foreach (var item in enumerableValue.Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("Collection_Value")] + [Benchmark(Baseline = true)] + public int Linq_Collection_Value() + { + var sum = 0; + foreach (var item in collectionValue.Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("List_Value")] + [Benchmark(Baseline = true)] + public int Linq_List_Value() + { + var sum = 0; + foreach (var item in listValue.Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public async ValueTask Linq_AsyncEnumerable_Value() + { + var sum = 0; + await foreach (var item in asyncEnumerableValue.Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark(Baseline = true)] + public int Linq_Enumerable_Reference() + { + var sum = 0; + foreach (var item in enumerableReference.Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("Collection_Reference")] + [Benchmark(Baseline = true)] + public int Linq_Collection_Reference() + { + var sum = 0; + foreach (var item in collectionReference.Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("List_Reference")] + [Benchmark(Baseline = true)] + public int Linq_List_Reference() + { + var sum = 0; + foreach (var item in listReference.Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public async ValueTask Linq_AsyncEnumerable_Reference() + { + var sum = 0; + await foreach (var item in asyncEnumerableReference.Select(item => item)) + sum += item; + return sum; + } // ------------------- @@ -91,97 +113,97 @@ public int StructLinq_Array() return sum; } - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark] - //public int StructLinq_Enumerable_Value() - //{ - // var sum = 0; - // foreach (var item in enumerableValue.ToStructEnumerable().Select(item => item, x => x)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark] - //public int StructLinq_Collection_Value() - //{ - // var sum = 0; - // foreach (var item in collectionValue.ToStructEnumerable().Select(item => item, x => x)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("List_Value")] - //[Benchmark] - //public int StructLinq_List_Value() - //{ - // var sum = 0; - // foreach (var item in listValue.ToStructEnumerable().Select(item => item, x => x)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark] - //public int StructLinq_Enumerable_Reference() - //{ - // var sum = 0; - // foreach (var item in enumerableReference.ToStructEnumerable().Select(item => item, x => x)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark] - //public int StructLinq_Collection_Reference() - //{ - // var sum = 0; - // foreach (var item in collectionReference.ToStructEnumerable().Select(item => item, x => x)) - // sum += item; - // return sum; - //} - - //[BenchmarkCategory("List_Reference")] - //[Benchmark] - //public int StructLinq_List_Reference() - //{ - // var sum = 0; - // foreach (var item in listReference.ToStructEnumerable().Select(item => item, x => x)) - // sum += item; - // return sum; - //} + [BenchmarkCategory("Enumerable_Value")] + [Benchmark] + public int StructLinq_Enumerable_Value() + { + var sum = 0; + foreach (var item in enumerableValue.ToStructEnumerable().Select(item => item, x => x)) + sum += item; + return sum; + } + + [BenchmarkCategory("Collection_Value")] + [Benchmark] + public int StructLinq_Collection_Value() + { + var sum = 0; + foreach (var item in collectionValue.ToStructEnumerable().Select(item => item, x => x)) + sum += item; + return sum; + } + + [BenchmarkCategory("List_Value")] + [Benchmark] + public int StructLinq_List_Value() + { + var sum = 0; + foreach (var item in listValue.ToStructEnumerable().Select(item => item, x => x)) + sum += item; + return sum; + } + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark] + public int StructLinq_Enumerable_Reference() + { + var sum = 0; + foreach (var item in enumerableReference.ToStructEnumerable().Select(item => item, x => x)) + sum += item; + return sum; + } + + [BenchmarkCategory("Collection_Reference")] + [Benchmark] + public int StructLinq_Collection_Reference() + { + var sum = 0; + foreach (var item in collectionReference.ToStructEnumerable().Select(item => item, x => x)) + sum += item; + return sum; + } + + [BenchmarkCategory("List_Reference")] + [Benchmark] + public int StructLinq_List_Reference() + { + var sum = 0; + foreach (var item in listReference.ToStructEnumerable().Select(item => item, x => x)) + sum += item; + return sum; + } // ------------------- -// [BenchmarkCategory("Array")] -// [Benchmark] -// public int Hyperlinq_Array_For() -// { -// var source = array.AsValueEnumerable().Select(item => item); -// var sum = 0; -// for (var index = 0; index < source.Count; index++) -// sum += source[index]; -// return sum; -// } - -//#pragma warning disable HLQ010 // Consider using a 'for' loop instead. -// [BenchmarkCategory("Array")] -// [Benchmark] -// public int Hyperlinq_Array_Foreach() -// { -// var sum = 0; -// foreach (var item in array.AsValueEnumerable().Select(item => item)) -// sum += item; -// return sum; -// } -//#pragma warning restore HLQ010 // Consider using a 'for' loop instead. + [BenchmarkCategory("Array")] + [Benchmark] + public int Hyperlinq_Array_For() + { + var source = array.AsValueEnumerable().Select(item => item); + var sum = 0; + for (var index = 0; index < source.Count; index++) + sum += source[index]; + return sum; + } + +#pragma warning disable HLQ010 // Consider using a 'for' loop instead. + [BenchmarkCategory("Array")] + [Benchmark] + public int Hyperlinq_Array_Foreach() + { + var sum = 0; + foreach (var item in array.AsValueEnumerable().Select(item => item)) + sum += item; + return sum; + } +#pragma warning restore HLQ010 // Consider using a 'for' loop instead. [BenchmarkCategory("Array")] [Benchmark] public int Hyperlinq_Span_For() { - var source = array.AsSpan().Select(item => item); + var source = array.AsSpan().AsValueEnumerable().Select(item => item); var sum = 0; for (var index = 0; index < source.Count; index++) sum += source[index]; @@ -194,7 +216,7 @@ public int Hyperlinq_Span_For() public int Hyperlinq_Span_Foreach() { var sum = 0; - foreach (var item in array.AsSpan().Select(item => item)) + foreach (var item in array.AsSpan().AsValueEnumerable().Select(item => item)) sum += item; return sum; } @@ -223,93 +245,88 @@ public int Hyperlinq_Memory_Foreach() } #pragma warning restore HLQ010 // Consider using a 'for' loop instead. - // [BenchmarkCategory("Enumerable_Value")] - // [Benchmark] - // public int Hyperlinq_Enumerable_Value() - // { - // var sum = 0; - // foreach (var item in EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) - // .Select(item => item)) - // sum += item; - // return sum; - // } - - // [BenchmarkCategory("Collection_Value")] - // [Benchmark] - // public int Hyperlinq_Collection_Value() - // { - // var sum = 0; - // foreach (var item in ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) - // .Select(item => item)) - // sum += item; - // return sum; - // } - - // [BenchmarkCategory("List_Value")] - // [Benchmark] - // public int Hyperlinq_List_Value_For() - // { - // var source = listValue.AsValueEnumerable().Select(item => item); - // var sum = 0; - // for (var index = 0; index < source.Count; index++) - // { - // var item = source[index]; - // sum += item; - // } - // return sum; - // } - - // [BenchmarkCategory("List_Value")] - // [Benchmark] - // public int Hyperlinq_List_Value_Foreach() - // { - // var sum = 0; - // foreach (var item in listValue.AsValueEnumerable().Select(item => item)) - // sum += item; - // return sum; - // } - - // [BenchmarkCategory("Enumerable_Reference")] - // [Benchmark] - // public int Hyperlinq_Enumerable_Reference() - // { - // var sum = 0; - // foreach (var item in enumerableReference.AsValueEnumerable().Select(item => item)) - // sum += item; - // return sum; - // } - - // [BenchmarkCategory("Collection_Reference")] - // [Benchmark] - // public int Hyperlinq_Collection_Reference() - // { - // var sum = 0; - // foreach (var item in collectionReference.AsValueEnumerable().Select(item => item)) - // sum += item; - // return sum; - // } - - // [BenchmarkCategory("List_Reference")] - // [Benchmark] - // public int Hyperlinq_List_Reference_For() - // { - // var source = listReference.AsValueEnumerable().Select(item => item); - // var sum = 0; - // for (var index = 0; index < source.Count; index++) - // sum += source[index]; - // return sum; - // } - - //#pragma warning disable HLQ010 // Consider using a 'for' loop instead. - // [BenchmarkCategory("List_Reference")] - // [Benchmark] - // public int Hyperlinq_List_Reference_Foreach() - // { - // var sum = 0; - // foreach (var item in listReference.AsValueEnumerable().Select(item => item)) - // sum += item; - // return sum; - // } - //#pragma warning restore HLQ010 // Consider using a 'for' loop instead. + [BenchmarkCategory("Enumerable_Value")] + [Benchmark] + public int Hyperlinq_Enumerable_Value() + { + var sum = 0; + foreach (var item in enumerableValue.AsValueEnumerable() + .Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("Collection_Value")] + [Benchmark] + public int Hyperlinq_Collection_Value() + { + var sum = 0; + foreach (var item in collectionValue.AsValueEnumerable() + .Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("List_Value")] + [Benchmark] + public int Hyperlinq_List_Value() + { + var sum = 0; + foreach (var item in listValue.AsValueEnumerable().Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public async ValueTask Hyperlinq_AsyncEnumerable_Value() + { + var sum = 0; + await foreach (var item in asyncEnumerableValue.AsAsyncValueEnumerable().Select((item, _) => new ValueTask(item))) + sum += item; + return sum; + } + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark] + public int Hyperlinq_Enumerable_Reference() + { + var sum = 0; + foreach (var item in enumerableReference.AsValueEnumerable().Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("Collection_Reference")] + [Benchmark] + public int Hyperlinq_Collection_Reference() + { + var sum = 0; + foreach (var item in collectionReference.AsValueEnumerable().Select(item => item)) + sum += item; + return sum; + } + +#pragma warning disable HLQ010 // Consider using a 'for' loop instead. + [BenchmarkCategory("List_Reference")] + [Benchmark] + public int Hyperlinq_List_Reference() + { + var sum = 0; + foreach (var item in listReference.AsValueEnumerable().Select(item => item)) + sum += item; + return sum; + } +#pragma warning restore HLQ010 // Consider using a 'for' loop instead. + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark] + public async ValueTask Hyperlinq_AsyncEnumerable_Reference() + { + var sum = 0; + await foreach (var item in asyncEnumerableReference.AsAsyncValueEnumerable().Select((item, _) => new ValueTask(item))) + sum += item; + return sum; + } } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectCountBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectCountBenchmarks.cs index 3dafd674d..0608b495c 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectCountBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectCountBenchmarks.cs @@ -1,7 +1,6 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using StructLinq; -using System; using System.Linq; using System.Threading.Tasks; @@ -14,55 +13,55 @@ public class SelectCountBenchmarks: RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() - => Enumerable.Select(array, item => item) + => array.Select(item => item) .Count(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Value() - => Enumerable.Select(enumerableValue, item => item) + => enumerableValue.Select(item => item) .Count(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int Linq_Collection_Value() - => Enumerable.Select(collectionValue, item => item) + => collectionValue.Select(item => item) .Count(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int Linq_List_Value() - => Enumerable.Select(listValue, item => item) + => listValue.Select(item => item) .Count(); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.Select(asyncEnumerableValue, item => item) + => asyncEnumerableValue.Select(item => item) .CountAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Reference() - => Enumerable.Select(enumerableReference, item => item) + => enumerableReference.Select(item => item) .Count(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int Linq_Collection_Reference() - => Enumerable.Select(collectionReference, item => item) + => collectionReference.Select(item => item) .Count(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int Linq_List_Reference() - => Enumerable.Select(listReference, item => item) + => listReference.Select(item => item) .Count(); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.Select(asyncEnumerableReference, item => item) + => asyncEnumerableReference.Select(item => item) .CountAsync(); // --------------------------------------------------------------------- @@ -128,36 +127,21 @@ public int StructLinq_List_Reference() [BenchmarkCategory("Array")] [Benchmark] public int Hyperlinq_Array() - => array - .Select(item => item) - .Count(); - - [BenchmarkCategory("Array")] - [Benchmark] - public int Hyperlinq_Span() - => array.AsSpan() + => array.AsValueEnumerable() .Select(item => item) .Count(); - [BenchmarkCategory("Array")] - [Benchmark] - public int Hyperlinq_Memory() - => memory.AsValueEnumerable() - .Select(item => item) - .Count(); - - [BenchmarkCategory("Enumerable_Value")] [Benchmark] public int Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Select(item => item) .Count(); [BenchmarkCategory("Collection_Value")] [Benchmark] public int Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Select(item => item) .Count(); @@ -173,8 +157,8 @@ public int Hyperlinq_List_Value() [Benchmark] public ValueTask Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - .Select(item => item) + .AsAsyncValueEnumerable() + .Select((item, _) => new ValueTask(item)) .CountAsync(); [BenchmarkCategory("Enumerable_Reference")] @@ -206,7 +190,7 @@ public int Hyperlinq_List_Reference() public ValueTask Hyperlinq_AsyncEnumerable_Reference() => asyncEnumerableReference .AsAsyncValueEnumerable() - .Select(item => item) + .Select((item, _) => new ValueTask(item)) .CountAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectManyBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectManyBenchmarks.cs index 521afd411..0374017e8 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectManyBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectManyBenchmarks.cs @@ -14,7 +14,7 @@ public class SelectManyBenchmarks : RandomBenchmarksBase public int Linq_Array() { var sum = 0; - foreach (var item in Enumerable.SelectMany(array, item => EnumerableEx.Return(item))) + foreach (var item in array.SelectMany(item => EnumerableEx.Return(item))) sum += item; return sum; } @@ -24,7 +24,7 @@ public int Linq_Array() public int Linq_Enumerable_Value() { var sum = 0; - foreach (var item in Enumerable.SelectMany(enumerableValue, item => EnumerableEx.Return(item))) + foreach (var item in enumerableValue.SelectMany(item => EnumerableEx.Return(item))) sum += item; return sum; } @@ -34,7 +34,7 @@ public int Linq_Enumerable_Value() public int Linq_Collection_Value() { var sum = 0; - foreach (var item in Enumerable.SelectMany(collectionValue, item => EnumerableEx.Return(item))) + foreach (var item in collectionValue.SelectMany(item => EnumerableEx.Return(item))) sum += item; return sum; } @@ -44,17 +44,17 @@ public int Linq_Collection_Value() public int Linq_List_Value() { var sum = 0; - foreach (var item in Enumerable.SelectMany(listValue, item => EnumerableEx.Return(item))) + foreach (var item in listValue.SelectMany(item => EnumerableEx.Return(item))) sum += item; return sum; } [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] - public async Task Linq_AsyncEnumerable_Value() + public async ValueTask Linq_AsyncEnumerable_Value() { var sum = 0; - await foreach (var item in AsyncEnumerable.SelectMany(asyncEnumerableValue, item => AsyncEnumerableEx.Return(item))) + await foreach (var item in asyncEnumerableValue.SelectMany(item => AsyncEnumerableEx.Return(item))) sum += item; return sum; } @@ -64,7 +64,7 @@ await foreach (var item in AsyncEnumerable.SelectMany(asyncEnumerableValue, item public int Linq_Enumerable_Reference() { var sum = 0; - foreach (var item in Enumerable.SelectMany(enumerableReference, item => EnumerableEx.Return(item))) + foreach (var item in enumerableReference.SelectMany(item => EnumerableEx.Return(item))) sum += item; return sum; } @@ -74,7 +74,7 @@ public int Linq_Enumerable_Reference() public int Linq_Collection_Reference() { var sum = 0; - foreach (var item in Enumerable.SelectMany(collectionReference, item => EnumerableEx.Return(item))) + foreach (var item in collectionReference.SelectMany(item => EnumerableEx.Return(item))) sum += item; return sum; } @@ -84,17 +84,17 @@ public int Linq_Collection_Reference() public int Linq_List_Reference() { var sum = 0; - foreach (var item in Enumerable.SelectMany(listReference, item => EnumerableEx.Return(item))) + foreach (var item in listReference.SelectMany(item => EnumerableEx.Return(item))) sum += item; return sum; } [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] - public async Task Linq_AsyncEnumerable_Reference() + public async ValueTask Linq_AsyncEnumerable_Reference() { var sum = 0; - await foreach (var item in AsyncEnumerable.SelectMany(asyncEnumerableReference, item => AsyncEnumerableEx.Return(item))) + await foreach (var item in asyncEnumerableReference.SelectMany(item => AsyncEnumerableEx.Return(item))) sum += item; return sum; } @@ -106,7 +106,8 @@ await foreach (var item in AsyncEnumerable.SelectMany(asyncEnumerableReference, public int Hyperlinq_Array() { var sum = 0; - foreach (var item in array.AsValueEnumerable().SelectMany, ValueEnumerable.ReturnEnumerable.DisposableEnumerator, int>(item => ValueEnumerable.Return(item))) + foreach (var item in array.AsValueEnumerable() + .SelectMany, ValueEnumerable.ReturnEnumerable.DisposableEnumerator, int>(item => ValueEnumerable.Return(item))) sum += item; return sum; } @@ -116,7 +117,8 @@ public int Hyperlinq_Array() public int Hyperlinq_Memory() { var sum = 0; - foreach (var item in memory.AsValueEnumerable().SelectMany, ValueEnumerable.ReturnEnumerable.DisposableEnumerator, int>(item => ValueEnumerable.Return(item))) + foreach (var item in memory.AsValueEnumerable() + .SelectMany, ValueEnumerable.ReturnEnumerable.DisposableEnumerator, int>(item => ValueEnumerable.Return(item))) sum += item; return sum; } @@ -126,7 +128,7 @@ public int Hyperlinq_Memory() public int Hyperlinq_Enumerable_Value() { var sum = 0; - foreach (var item in EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + foreach (var item in enumerableValue.AsValueEnumerable() .SelectMany(item => ValueEnumerable.Return(item))) sum += item; return sum; @@ -137,7 +139,7 @@ public int Hyperlinq_Enumerable_Value() public int Hyperlinq_Collection_Value() { var sum = 0; - foreach (var item in EnumerableExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + foreach (var item in collectionValue.AsValueEnumerable() .SelectMany(item => ValueEnumerable.Return(item))) sum += item; return sum; diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectSumBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectSumBenchmarks.cs index b0d70fc17..0d46e2429 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectSumBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectSumBenchmarks.cs @@ -1,7 +1,6 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using StructLinq; -using System; using System.Linq; using System.Threading.Tasks; @@ -14,56 +13,56 @@ public class SelectSumBenchmarks: RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() - => Enumerable.Select(array, item => item) + => array.Select(item => item) .Sum(); - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark(Baseline = true)] - //public int Linq_Enumerable_Value() - // => Enumerable.Select(enumerableValue, item => item) - // .Sum(); - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark(Baseline = true)] - //public int Linq_Collection_Value() - // => Enumerable.Select(collectionValue, item => item) - // .Sum(); - - //[BenchmarkCategory("List_Value")] - //[Benchmark(Baseline = true)] - //public int Linq_List_Value() - // => Enumerable.Select(listValue, item => item) - // .Sum(); - - //[BenchmarkCategory("AsyncEnumerable_Value")] - //[Benchmark(Baseline = true)] - //public ValueTask Linq_AsyncEnumerable_Value() - // => AsyncEnumerable.Select(asyncEnumerableValue, item => item) - // .SumAsync(); - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark(Baseline = true)] - //public int Linq_Enumerable_Reference() - // => Enumerable.Select(enumerableReference, item => item) - // .Sum(); - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark(Baseline = true)] - //public int Linq_Collection_Reference() - // => Enumerable.Select(collectionReference, item => item) - // .Sum(); - - //[BenchmarkCategory("List_Reference")] - //[Benchmark(Baseline = true)] - //public int Linq_List_Reference() - // => Enumerable.Select(listReference, item => item) - // .Sum(); - - //[BenchmarkCategory("AsyncEnumerable_Reference")] - //[Benchmark(Baseline = true)] - //public ValueTask Linq_AsyncEnumerable_Reference() - // => AsyncEnumerable.Select(asyncEnumerableReference, item => item) - // .SumAsync(); + [BenchmarkCategory("Enumerable_Value")] + [Benchmark(Baseline = true)] + public int Linq_Enumerable_Value() + => enumerableValue.Select(item => item) + .Sum(); + + [BenchmarkCategory("Collection_Value")] + [Benchmark(Baseline = true)] + public int Linq_Collection_Value() + => collectionValue.Select(item => item) + .Sum(); + + [BenchmarkCategory("List_Value")] + [Benchmark(Baseline = true)] + public int Linq_List_Value() + => listValue.Select(item => item) + .Sum(); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Value() + => asyncEnumerableValue.Select(item => item) + .SumAsync(); + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark(Baseline = true)] + public int Linq_Enumerable_Reference() + => enumerableReference.Select(item => item) + .Sum(); + + [BenchmarkCategory("Collection_Reference")] + [Benchmark(Baseline = true)] + public int Linq_Collection_Reference() + => collectionReference.Select(item => item) + .Sum(); + + [BenchmarkCategory("List_Reference")] + [Benchmark(Baseline = true)] + public int Linq_List_Reference() + => listReference.Select(item => item) + .Sum(); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Reference() + => asyncEnumerableReference.Select(item => item) + .SumAsync(); // --------------------------------------------------------------------- @@ -75,53 +74,53 @@ public int StructLinq_Array() .Select(item => item, x => x) .Sum(x => x); - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark] - //public int StructLinq_Enumerable_Value() - // => enumerableValue - // .ToStructEnumerable() - // .Select(item => item, x => x) - // .Sum(x => x); - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark] - //public int StructLinq_Collection_Value() - // => collectionValue - // .ToStructEnumerable() - // .Select(item => item, x => x) - // .Sum(x => x); - - //[BenchmarkCategory("List_Value")] - //[Benchmark] - //public int StructLinq_List_Value() - // => listValue - // .ToStructEnumerable() - // .Select(item => item, x => x) - // .Sum(x => x); - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark] - //public int StructLinq_Enumerable_Reference() - // => enumerableReference - // .ToStructEnumerable() - // .Select(item => item, x => x) - // .Sum(x => x); - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark] - //public int StructLinq_Collection_Reference() - // => collectionReference - // .ToStructEnumerable() - // .Select(item => item, x => x) - // .Sum(x => x); - - //[BenchmarkCategory("List_Reference")] - //[Benchmark] - //public int StructLinq_List_Reference() - // => listReference - // .ToStructEnumerable() - // .Select(item => item, x => x) - // .Sum(x => x); + [BenchmarkCategory("Enumerable_Value")] + [Benchmark] + public int StructLinq_Enumerable_Value() + => enumerableValue + .ToStructEnumerable() + .Select(item => item, x => x) + .Sum(x => x); + + [BenchmarkCategory("Collection_Value")] + [Benchmark] + public int StructLinq_Collection_Value() + => collectionValue + .ToStructEnumerable() + .Select(item => item, x => x) + .Sum(x => x); + + [BenchmarkCategory("List_Value")] + [Benchmark] + public int StructLinq_List_Value() + => listValue + .ToStructEnumerable() + .Select(item => item, x => x) + .Sum(x => x); + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark] + public int StructLinq_Enumerable_Reference() + => enumerableReference + .ToStructEnumerable() + .Select(item => item, x => x) + .Sum(x => x); + + [BenchmarkCategory("Collection_Reference")] + [Benchmark] + public int StructLinq_Collection_Reference() + => collectionReference + .ToStructEnumerable() + .Select(item => item, x => x) + .Sum(x => x); + + [BenchmarkCategory("List_Reference")] + [Benchmark] + public int StructLinq_List_Reference() + => listReference + .ToStructEnumerable() + .Select(item => item, x => x) + .Sum(x => x); // --------------------------------------------------------------------- @@ -134,86 +133,71 @@ public int Hyperlinq_Array() [BenchmarkCategory("Array")] [Benchmark] - public int Hyperlinq_Span() - => array.AsSpan() + public int Hyperlinq_Array_SIMD() + => array.AsValueEnumerable() + .SelectVector(item => item, item => item) + .Sum(); + + [BenchmarkCategory("Enumerable_Value")] + [Benchmark] + public int Hyperlinq_Enumerable_Value() + => enumerableValue.AsValueEnumerable() .Select(item => item) .Sum(); - [BenchmarkCategory("Array")] + [BenchmarkCategory("Collection_Value")] [Benchmark] - public int Hyperlinq_Span_SIMD() - => array.AsSpan() - .SelectVector(item => item, item => item) + public int Hyperlinq_Collection_Value() + => collectionValue.AsValueEnumerable() + .Select(item => item) .Sum(); - //[BenchmarkCategory("Array")] - //[Benchmark] - //public int Hyperlinq_Memory() - // => memory.AsValueEnumerable() - // .Select(item => item) - // .Sum(); - - - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark] - //public int Hyperlinq_Enumerable_Value() - // => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) - // .Select(item => item) - // .Sum(); - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark] - //public int Hyperlinq_Collection_Value() - // => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) - // .Select(item => item) - // .Sum(); - - //[BenchmarkCategory("List_Value")] - //[Benchmark] - //public int Hyperlinq_List_Value() - // => listValue - // .AsValueEnumerable() - // .Select(item => item) - // .Sum(); - - //[BenchmarkCategory("AsyncEnumerable_Value")] - //[Benchmark] - //public ValueTask Hyperlinq_AsyncEnumerable_Value() - // => asyncEnumerableValue - // .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - // .Select(item => item) - // .SumAsync(); - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark] - //public int Hyperlinq_Enumerable_Reference() - // => enumerableReference - // .AsValueEnumerable() - // .Select(item => item) - // .Sum(); - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark] - //public int Hyperlinq_Collection_Reference() - // => collectionReference - // .AsValueEnumerable() - // .Select(item => item) - // .Sum(); - - //[BenchmarkCategory("List_Reference")] - //[Benchmark] - //public int Hyperlinq_List_Reference() - // => listReference - // .AsValueEnumerable() - // .Select(item => item) - // .Sum(); - - //[BenchmarkCategory("AsyncEnumerable_Reference")] - //[Benchmark] - //public ValueTask Hyperlinq_AsyncEnumerable_Reference() - // => asyncEnumerableReference - // .AsAsyncValueEnumerable() - // .Select(item => item) - // .SumAsync(); + [BenchmarkCategory("List_Value")] + [Benchmark] + public int Hyperlinq_List_Value() + => listValue + .AsValueEnumerable() + .Select(item => item) + .Sum(); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public ValueTask Hyperlinq_AsyncEnumerable_Value() + => asyncEnumerableValue + .AsAsyncValueEnumerable() + .Select((item, _) => new ValueTask(item)) + .SumAsync(); + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark] + public int Hyperlinq_Enumerable_Reference() + => enumerableReference + .AsValueEnumerable() + .Select(item => item) + .Sum(); + + [BenchmarkCategory("Collection_Reference")] + [Benchmark] + public int Hyperlinq_Collection_Reference() + => collectionReference + .AsValueEnumerable() + .Select(item => item) + .Sum(); + + [BenchmarkCategory("List_Reference")] + [Benchmark] + public int Hyperlinq_List_Reference() + => listReference + .AsValueEnumerable() + .Select(item => item) + .Sum(); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark] + public ValueTask Hyperlinq_AsyncEnumerable_Reference() + => asyncEnumerableReference + .AsAsyncValueEnumerable() + .Select((item, _) => new ValueTask(item)) + .SumAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToArrayBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToArrayBenchmarks.cs index 8c80563b4..d1050b589 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToArrayBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToArrayBenchmarks.cs @@ -2,7 +2,6 @@ using BenchmarkDotNet.Configs; using JM.LinqFaster.SIMD; using StructLinq; -using System; using System.Linq; using System.Threading.Tasks; @@ -15,37 +14,47 @@ public class SelectToArrayBenchmarks : RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int[] Linq_Array() - => Enumerable.Select(array, item => item).ToArray(); + => array.Select(item => item).ToArray(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int[] Linq_Enumerable_Value() - => Enumerable.Select(enumerableValue, item => item).ToArray(); + => enumerableValue.Select(item => item).ToArray(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int[] Linq_Collection_Value() - => Enumerable.Select(collectionValue, item => item).ToArray(); + => collectionValue.Select(item => item).ToArray(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int[] Linq_List_Value() - => Enumerable.Select(listValue, item => item).ToArray(); + => listValue.Select(item => item).ToArray(); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Value() + => asyncEnumerableValue.Select(item => item).ToArrayAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int[] Linq_Enumerable_Reference() - => Enumerable.Select(enumerableReference, item => item).ToArray(); + => enumerableReference.Select(item => item).ToArray(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int[] Linq_Collection_Reference() - => Enumerable.Select(collectionReference, item => item).ToArray(); + => collectionReference.Select(item => item).ToArray(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int[] Linq_List_Reference() - => Enumerable.Select(listReference, item => item).ToArray(); + => listReference.Select(item => item).ToArray(); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Reference() + => asyncEnumerableReference.Select(item => item).ToArrayAsync(); // --------------------------------------------------------------------- @@ -124,36 +133,22 @@ public int[] Hyperlinq_Array() [BenchmarkCategory("Array")] [Benchmark] - public int[] Hyperlinq_Span() - => array.AsSpan() - .Select(item => item) - .ToArray(); - - [BenchmarkCategory("Array")] - [Benchmark] - public int[] Hyperlinq_Span_SIMD() - => array.AsSpan() + public int[] Hyperlinq_Array_SIMD() + => array.AsValueEnumerable() .SelectVector(item => item, item => item) .ToArray(); - [BenchmarkCategory("Array")] - [Benchmark] - public int[] Hyperlinq_Memory() - => memory.AsValueEnumerable() - .Select(item => item) - .ToArray(); - [BenchmarkCategory("Enumerable_Value")] [Benchmark] public int[] Hyperlinq_Enumerable_Value() - => enumerableValue.AsValueEnumerable(enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Select(item => item) .ToArray(); [BenchmarkCategory("Collection_Value")] [Benchmark] public int[] Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Select(item => item) .ToArray(); @@ -169,8 +164,8 @@ public int[] Hyperlinq_List_Value() [Benchmark] public ValueTask Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - .Select(item => item) + .AsAsyncValueEnumerable() + .Select((item, _) => new ValueTask(item)) .ToArrayAsync(); [BenchmarkCategory("Enumerable_Reference")] @@ -202,7 +197,7 @@ public int[] Hyperlinq_List_Reference() public ValueTask Hyperlinq_AsyncEnumerable_Reference() => asyncEnumerableReference .AsAsyncValueEnumerable() - .Select(item => item) + .Select((item, _) => new ValueTask(item)) .ToArrayAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToListBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToListBenchmarks.cs index f5f3f0b00..5fd9f1031 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToListBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SelectToListBenchmarks.cs @@ -1,7 +1,6 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using StructLinq; -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -14,44 +13,56 @@ public class SelectToListBenchmarks: RandomBenchmarksBase { [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] - public List Linq_List() - => Enumerable.Select(array, item => item).ToList(); + public List Linq_Array() + => array.Select(item => item).ToList(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public List Linq_Enumerable_Value() - => Enumerable.Select(enumerableValue, item => item).ToList(); + => enumerableValue.Select(item => item).ToList(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public List Linq_Collection_Value() - => Enumerable.Select(collectionValue, item => item).ToList(); + => collectionValue.Select(item => item).ToList(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public List Linq_List_Value() - => Enumerable.Select(listValue, item => item).ToList(); + => listValue.Select(item => item).ToList(); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public ValueTask> Linq_AsyncEnumerable_Value() + => asyncEnumerableValue.Select(item => item) + .ToListAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public List Linq_Enumerable_Reference() - => Enumerable.Select(enumerableReference, item => item).ToList(); + => enumerableReference.Select(item => item).ToList(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public List Linq_Collection_Reference() - => Enumerable.Select(collectionReference, item => item).ToList(); + => collectionReference.Select(item => item).ToList(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public List Linq_List_Reference() - => Enumerable.Select(listReference, item => item).ToList(); + => listReference.Select(item => item).ToList(); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public ValueTask> Linq_AsyncEnumerable_Reference() + => asyncEnumerableReference.Select(item => item) + .ToListAsync(); // --------------------------------------------------------------------- [BenchmarkCategory("Array")] [Benchmark] - public List StructLinq_List() + public List StructLinq_Array() => array .ToStructEnumerable() .Select(item => item, x => x) @@ -109,36 +120,29 @@ public List StructLinq_List_Reference() [BenchmarkCategory("Array")] [Benchmark] - public List Hyperlinq_List() - => array - .Select(item => item) - .ToList(); - - [BenchmarkCategory("Array")] - [Benchmark] - public List Hyperlinq_Span() - => array.AsSpan() + public List Hyperlinq_Array() + => array.AsValueEnumerable() .Select(item => item) .ToList(); [BenchmarkCategory("Array")] [Benchmark] - public List Hyperlinq_Memory() - => memory.AsValueEnumerable() - .Select(item => item) + public List Hyperlinq_Array_SIMD() + => array.AsValueEnumerable() + .SelectVector(item => item, item => item) .ToList(); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public List Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Select(item => item) .ToList(); [BenchmarkCategory("Collection_Value")] [Benchmark] public List Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Select(item => item) .ToList(); @@ -154,8 +158,8 @@ public List Hyperlinq_List_Value() [Benchmark] public ValueTask> Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - .Select(item => item) + .AsAsyncValueEnumerable() + .Select((item, _) => new ValueTask(item)) .ToListAsync(); [BenchmarkCategory("Enumerable_Reference")] @@ -187,7 +191,7 @@ public List Hyperlinq_List_Reference() public ValueTask> Hyperlinq_AsyncEnumerable_Reference() => asyncEnumerableReference .AsAsyncValueEnumerable() - .Select(item => item) + .Select((item, _) => new ValueTask(item)) .ToListAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SingleBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SingleBenchmarks.cs index 37f289a4e..93cf2814a 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SingleBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SingleBenchmarks.cs @@ -2,10 +2,7 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using System; -using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; namespace NetFabric.Hyperlinq.Benchmarks @@ -18,47 +15,47 @@ public class SingleBenchmarks : SingleBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() => - Enumerable.Single(array); + array.Single(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Value() => - Enumerable.Single(enumerableValue); + enumerableValue.Single(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int Linq_Collection_Value() => - Enumerable.Single(collectionValue); + collectionValue.Single(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int Linq_List_Value() => - Enumerable.Single(listValue); + listValue.Single(); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() => - AsyncEnumerable.SingleAsync(asyncEnumerableValue); + asyncEnumerableValue.SingleAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Reference() => - Enumerable.Single(enumerableReference); + enumerableReference.Single(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int Linq_Collection_Reference() => - Enumerable.Single(collectionReference); + collectionReference.Single(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int Linq_List_Reference() => - Enumerable.Single(listReference); + listReference.Single(); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() => - AsyncEnumerable.SingleAsync(asyncEnumerableReference); + asyncEnumerableReference.SingleAsync(); // --------------------------------------------------------------------- @@ -67,26 +64,16 @@ public class SingleBenchmarks : SingleBenchmarksBase public Option Hyperlinq_Array() => array.AsValueEnumerable().Single(); - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Span() => - array.AsSpan().Single(); - - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Memory() => - memory.AsValueEnumerable().Single(); - [BenchmarkCategory("Enumerable_Value")] [Benchmark] public Option Hyperlinq_Enumerable_Value() => - EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + enumerableValue.AsValueEnumerable() .Single(); [BenchmarkCategory("Collection_Value")] [Benchmark] public Option Hyperlinq_Collection_Value() => - ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + collectionValue.AsValueEnumerable() .Single(); [BenchmarkCategory("List_Value")] @@ -96,11 +83,11 @@ public class SingleBenchmarks : SingleBenchmarksBase .AsValueEnumerable() .Single(); - [BenchmarkCategory("AsyncEnumerable_Value")] - [Benchmark] - public ValueTask> Hyperlinq_AsyncEnumerable_Value() => - asyncEnumerableValue.AsAsyncValueEnumerable((enumerable, cancellationToken) => enumerable.GetAsyncEnumerator(cancellationToken)) - .SingleAsync(); + // [BenchmarkCategory("AsyncEnumerable_Value")] + // [Benchmark] + // public ValueTask> Hyperlinq_AsyncEnumerable_Value() => + // asyncEnumerableValue.AsAsyncValueEnumerable() + // .SingleAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark] @@ -123,11 +110,11 @@ public class SingleBenchmarks : SingleBenchmarksBase .AsValueEnumerable() .Single(); - [BenchmarkCategory("AsyncEnumerable_Reference")] - [Benchmark] - public ValueTask> Hyperlinq_AsyncEnumerable_Reference() => - asyncEnumerableReference.AsAsyncValueEnumerable() - .SingleAsync(); + // [BenchmarkCategory("AsyncEnumerable_Reference")] + // [Benchmark] + // public ValueTask> Hyperlinq_AsyncEnumerable_Reference() => + // asyncEnumerableReference.AsAsyncValueEnumerable() + // .SingleAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SkipTakeBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SkipTakeBenchmarks.cs index 8164ffcd7..39fe01e62 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SkipTakeBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SkipTakeBenchmarks.cs @@ -16,7 +16,7 @@ public class SkipTakeBenchmarks : RandomSkipBenchmarksBase public int Linq_Array() { var sum = 0; - foreach (var item in Enumerable.Skip(array, Skip).Take(Count)) + foreach (var item in array.Skip(Skip).Take(Count)) sum += item; return sum; } @@ -26,7 +26,7 @@ public int Linq_Array() public int Linq_Enumerable_Value() { var sum = 0; - foreach (var item in Enumerable.Skip(enumerableValue, Skip).Take(Count)) + foreach (var item in enumerableValue.Skip(Skip).Take(Count)) sum += item; return sum; } @@ -36,7 +36,7 @@ public int Linq_Enumerable_Value() public int Linq_Collection_Value() { var sum = 0; - foreach (var item in Enumerable.Skip(collectionValue, Skip).Take(Count)) + foreach (var item in collectionValue.Skip(Skip).Take(Count)) sum += item; return sum; } @@ -46,17 +46,17 @@ public int Linq_Collection_Value() public int Linq_List_Value() { var sum = 0; - foreach (var item in Enumerable.Skip(listValue, Skip).Take(Count)) + foreach (var item in listValue.Skip(Skip).Take(Count)) sum += item; return sum; } [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] - public async Task Linq_AsyncEnumerable_Value() + public async ValueTask Linq_AsyncEnumerable_Value() { var sum = 0; - await foreach (var item in AsyncEnumerable.Skip(asyncEnumerableValue, Skip).Take(Count)) + await foreach (var item in asyncEnumerableValue.Skip(Skip).Take(Count)) sum += item; return sum; } @@ -66,7 +66,7 @@ await foreach (var item in AsyncEnumerable.Skip(asyncEnumerableValue, Skip).Take public int Linq_Enumerable_Reference() { var sum = 0; - foreach (var item in Enumerable.Skip(enumerableReference, Skip).Take(Count)) + foreach (var item in enumerableReference.Skip(Skip).Take(Count)) sum += item; return sum; } @@ -76,7 +76,7 @@ public int Linq_Enumerable_Reference() public int Linq_Collection_Reference() { var sum = 0; - foreach (var item in Enumerable.Skip(collectionReference, Skip).Take(Count)) + foreach (var item in collectionReference.Skip(Skip).Take(Count)) sum += item; return sum; } @@ -86,17 +86,17 @@ public int Linq_Collection_Reference() public int Linq_List_Reference() { var sum = 0; - foreach (var item in Enumerable.Skip(listReference, Skip).Take(Count)) + foreach (var item in listReference.Skip(Skip).Take(Count)) sum += item; return sum; } [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] - public async Task Linq_AsyncEnumerable_Reference() + public async ValueTask Linq_AsyncEnumerable_Reference() { var sum = 0; - await foreach (var item in AsyncEnumerable.Skip(asyncEnumerableReference, Skip).Take(Count)) + await foreach (var item in asyncEnumerableReference.Skip(Skip).Take(Count)) sum += item; return sum; } @@ -207,9 +207,9 @@ public int Hyperlinq_Array_Foreach() [Benchmark] public int Hyperlinq_Span_For() { - var source = array.AsSpan().Skip(Skip).Take(Count); + var source = array.AsSpan().AsValueEnumerable().Skip(Skip).Take(Count); var sum = 0; - for (var index = 0; index < source.Length; index++) + for (var index = 0; index < source.Count; index++) { var item = source[index]; sum += item; @@ -223,7 +223,7 @@ public int Hyperlinq_Span_For() public int Hyperlinq_Span_Foreach() { var sum = 0; - foreach (var item in array.AsSpan().Skip(Skip).Take(Count)) + foreach (var item in array.AsSpan().AsValueEnumerable().Skip(Skip).Take(Count)) sum += item; return sum; } @@ -260,7 +260,7 @@ public int Hyperlinq_Memory_Foreach() public int Hyperlinq_Enumerable_Value() { var sum = 0; - foreach (var item in EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + foreach (var item in enumerableValue.AsValueEnumerable() .Skip(Skip) .Take(Count)) sum += item; @@ -272,7 +272,7 @@ public int Hyperlinq_Enumerable_Value() public int Hyperlinq_Collection_Value() { var sum = 0; - foreach (var item in ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + foreach (var item in collectionValue.AsValueEnumerable() .Skip(Skip) .Take(Count)) sum += item; @@ -305,10 +305,10 @@ public int Hyperlinq_List_Value_Foreach() [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark] - public async Task Hyperlinq_AsyncEnumerable_Value() + public async ValueTask Hyperlinq_AsyncEnumerable_Value() { var sum = 0; - await foreach (var item in asyncEnumerableValue.AsAsyncValueEnumerable((enumerable, cancellationToken) => enumerable.GetAsyncEnumerator(cancellationToken)) + await foreach (var item in asyncEnumerableValue.AsAsyncValueEnumerable() .Skip(Skip) .Take(Count)) sum += item; @@ -360,7 +360,7 @@ public int Hyperlinq_List_Reference_Foreach() [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark] - public async Task Hyperlinq_AsyncEnumerable_Reference() + public async ValueTask Hyperlinq_AsyncEnumerable_Reference() { var sum = 0; await foreach (var item in asyncEnumerableReference.AsAsyncValueEnumerable() diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SumBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SumBenchmarks.cs index aa03fabae..9c4cbefb4 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SumBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/SumBenchmarks.cs @@ -2,7 +2,6 @@ using BenchmarkDotNet.Configs; using JM.LinqFaster.SIMD; using StructLinq; -using System; using System.Linq; using System.Threading.Tasks; @@ -17,45 +16,45 @@ public class SumBenchmarks : RandomBenchmarksBase public int Linq_Array() => Enumerable.Sum(array); - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark(Baseline = true)] - //public int Linq_Enumerable_Value() - // => Enumerable.Sum(enumerableValue); - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark(Baseline = true)] - //public int Linq_Collection_Value() - // => Enumerable.Sum(collectionValue); - - //[BenchmarkCategory("List_Value")] - //[Benchmark(Baseline = true)] - //public int Linq_List_Value() - // => Enumerable.Sum(listValue); - - //[BenchmarkCategory("AsyncEnumerable_Value")] - //[Benchmark(Baseline = true)] - //public ValueTask Linq_AsyncEnumerable_Value() - // => AsyncEnumerable.SumAsync(asyncEnumerableValue); - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark(Baseline = true)] - //public int Linq_Enumerable_Reference() - // => Enumerable.Sum(enumerableReference); - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark(Baseline = true)] - //public int Linq_Collection_Reference() - // => Enumerable.Sum(collectionReference); - - //[BenchmarkCategory("List_Reference")] - //[Benchmark(Baseline = true)] - //public int Linq_List_Reference() - // => Enumerable.Sum(listReference); - - //[BenchmarkCategory("AsyncEnumerable_Reference")] - //[Benchmark(Baseline = true)] - //public ValueTask Linq_AsyncEnumerable_Reference() - // => AsyncEnumerable.SumAsync(asyncEnumerableReference); + [BenchmarkCategory("Enumerable_Value")] + [Benchmark(Baseline = true)] + public int Linq_Enumerable_Value() + => Enumerable.Sum(enumerableValue); + + [BenchmarkCategory("Collection_Value")] + [Benchmark(Baseline = true)] + public int Linq_Collection_Value() + => Enumerable.Sum(collectionValue); + + [BenchmarkCategory("List_Value")] + [Benchmark(Baseline = true)] + public int Linq_List_Value() + => Enumerable.Sum(listValue); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Value() + => AsyncEnumerable.SumAsync(asyncEnumerableValue); + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark(Baseline = true)] + public int Linq_Enumerable_Reference() + => Enumerable.Sum(enumerableReference); + + [BenchmarkCategory("Collection_Reference")] + [Benchmark(Baseline = true)] + public int Linq_Collection_Reference() + => Enumerable.Sum(collectionReference); + + [BenchmarkCategory("List_Reference")] + [Benchmark(Baseline = true)] + public int Linq_List_Reference() + => Enumerable.Sum(listReference); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Reference() + => AsyncEnumerable.SumAsync(asyncEnumerableReference); // --------------------------------------------------------------------- @@ -66,47 +65,47 @@ public int StructLinq_Array() .ToStructEnumerable() .Sum(x => x); - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark] - //public int StructLinq_Enumerable_Value() - // => enumerableValue - // .ToStructEnumerable() - // .Sum(x => x); - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark] - //public int StructLinq_Collection_Value() - // => collectionValue - // .ToStructEnumerable() - // .Sum(x => x); - - //[BenchmarkCategory("List_Value")] - //[Benchmark] - //public int StructLinq_List_Value() - // => listValue - // .ToStructEnumerable() - // .Sum(x => x); - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark] - //public int StructLinq_Enumerable_Reference() - // => enumerableReference - // .ToStructEnumerable() - // .Sum(x => x); - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark] - //public int StructLinq_Collection_Reference() - // => collectionReference - // .ToStructEnumerable() - // .Sum(x => x); - - //[BenchmarkCategory("List_Reference")] - //[Benchmark] - //public int StructLinq_List_Reference() - // => listReference - // .ToStructEnumerable() - // .Sum(x => x); + [BenchmarkCategory("Enumerable_Value")] + [Benchmark] + public int StructLinq_Enumerable_Value() + => enumerableValue + .ToStructEnumerable() + .Sum(x => x); + + [BenchmarkCategory("Collection_Value")] + [Benchmark] + public int StructLinq_Collection_Value() + => collectionValue + .ToStructEnumerable() + .Sum(x => x); + + [BenchmarkCategory("List_Value")] + [Benchmark] + public int StructLinq_List_Value() + => listValue + .ToStructEnumerable() + .Sum(x => x); + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark] + public int StructLinq_Enumerable_Reference() + => enumerableReference + .ToStructEnumerable() + .Sum(x => x); + + [BenchmarkCategory("Collection_Reference")] + [Benchmark] + public int StructLinq_Collection_Reference() + => collectionReference + .ToStructEnumerable() + .Sum(x => x); + + [BenchmarkCategory("List_Reference")] + [Benchmark] + public int StructLinq_List_Reference() + => listReference + .ToStructEnumerable() + .Sum(x => x); // --------------------------------------------------------------------- @@ -123,68 +122,58 @@ public int LinqFasterSIMD_Array() public int Hyperlinq_Array() => array.AsValueEnumerable().Sum(); - [BenchmarkCategory("Array")] + [BenchmarkCategory("Enumerable_Value")] + [Benchmark] + public int Hyperlinq_Enumerable_Value() + => enumerableValue.AsValueEnumerable() + .Sum(); + + [BenchmarkCategory("Collection_Value")] + [Benchmark] + public int Hyperlinq_Collection_Value() + => collectionValue.AsValueEnumerable() + .Sum(); + + [BenchmarkCategory("List_Value")] + [Benchmark] + public int Hyperlinq_List_Value() + => listValue + .AsValueEnumerable() + .Sum(); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public ValueTask Hyperlinq_AsyncEnumerable_Value() + => asyncEnumerableValue + .AsAsyncValueEnumerable() + .SumAsync(); + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark] + public int Hyperlinq_Enumerable_Reference() + => enumerableReference + .AsValueEnumerable() + .Sum(); + + [BenchmarkCategory("Collection_Reference")] + [Benchmark] + public int Hyperlinq_Collection_Reference() + => collectionReference + .AsValueEnumerable() + .Sum(); + + [BenchmarkCategory("List_Reference")] + [Benchmark] + public int Hyperlinq_List_Reference() + => listReference + .AsValueEnumerable() + .Sum(); + + [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark] - public int Hyperlinq_Span() - => array.AsSpan().Sum(); - - //[BenchmarkCategory("Array")] - //[Benchmark] - //public int Hyperlinq_Memory() - // => memory.Sum(); - - //[BenchmarkCategory("Enumerable_Value")] - //[Benchmark] - //public int Hyperlinq_Enumerable_Value() - // => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) - // .Sum(); - - //[BenchmarkCategory("Collection_Value")] - //[Benchmark] - //public int Hyperlinq_Collection_Value() - // => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) - // .Sum(); - - //[BenchmarkCategory("List_Value")] - //[Benchmark] - //public int Hyperlinq_List_Value() - // => listValue - // .AsValueEnumerable() - // .Sum(); - - //[BenchmarkCategory("AsyncEnumerable_Value")] - //[Benchmark] - //public ValueTask Hyperlinq_AsyncEnumerable_Value() - // => asyncEnumerableValue - // .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - // .SumAsync(); - - //[BenchmarkCategory("Enumerable_Reference")] - //[Benchmark] - //public int Hyperlinq_Enumerable_Reference() - // => enumerableReference - // .AsValueEnumerable() - // .Sum(); - - //[BenchmarkCategory("Collection_Reference")] - //[Benchmark] - //public int Hyperlinq_Collection_Reference() - // => collectionReference - // .AsValueEnumerable() - // .Sum(); - - //[BenchmarkCategory("List_Reference")] - //[Benchmark] - //public int Hyperlinq_List_Reference() - // => listReference - // .AsValueEnumerable() - // .Sum(); - - //[BenchmarkCategory("AsyncEnumerable_Reference")] - //[Benchmark] - //public ValueTask Hyperlinq_AsyncEnumerable_Reference() - // => asyncEnumerableReference - // .AsAsyncValueEnumerable() - // .SumAsync(); + public ValueTask Hyperlinq_AsyncEnumerable_Reference() + => asyncEnumerableReference + .AsAsyncValueEnumerable() + .SumAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToArrayBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToArrayBenchmarks.cs index 2e89202a1..ea474c86c 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToArrayBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToArrayBenchmarks.cs @@ -1,7 +1,7 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using StructLinq; -using System; +using System.Buffers; using System.Linq; using System.Threading.Tasks; @@ -14,37 +14,49 @@ public class ToArrayBenchmarks: RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int[] Linq_Array() - => Enumerable.ToArray(array); + => array.ToArray(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int[] Linq_Enumerable_Value() - => Enumerable.ToArray(enumerableValue); + => enumerableValue.ToArray(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int[] Linq_Collection_Value() - => Enumerable.ToArray(collectionValue); + => collectionValue.ToArray(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int[] Linq_List_Value() - => Enumerable.ToArray(listValue); + => listValue.ToArray(); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Value() + => asyncEnumerableValue + .ToArrayAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int[] Linq_Enumerable_Reference() - => Enumerable.ToArray(enumerableReference); + => enumerableReference.ToArray(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int[] Linq_Collection_Reference() - => Enumerable.ToArray(collectionReference); + => collectionReference.ToArray(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int[] Linq_List_Reference() - => Enumerable.ToArray(listReference); + => listReference.ToArray(); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Reference() + => asyncEnumerableReference + .ToArrayAsync(); // --------------------------------------------------------------------- @@ -102,31 +114,19 @@ public int[] StructLinq_List_Reference() [BenchmarkCategory("Array")] [Benchmark] public int[] Hyperlinq_Array() - => array - .ToArray(); - - [BenchmarkCategory("Array")] - [Benchmark] - public int[] Hyperlinq_Span() - => array.AsSpan() - .ToArray(); - - [BenchmarkCategory("Array")] - [Benchmark] - public int[] Hyperlinq_Memory() - => memory + => array.AsValueEnumerable() .ToArray(); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public int[] Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .ToArray(); [BenchmarkCategory("Collection_Value")] [Benchmark] public int[] Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .ToArray(); [BenchmarkCategory("List_Value")] @@ -140,7 +140,7 @@ public int[] Hyperlinq_List_Value() [Benchmark] public ValueTask Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) + .AsAsyncValueEnumerable() .ToArrayAsync(); [BenchmarkCategory("Enumerable_Reference")] @@ -170,5 +170,94 @@ public ValueTask Hyperlinq_AsyncEnumerable_Reference() => asyncEnumerableReference .AsAsyncValueEnumerable() .ToArrayAsync(); + + // --------------------------------------------------------------------- + + [BenchmarkCategory("Array")] + [Benchmark] + public IMemoryOwner Hyperlinq_Array_ArrayPool() + { + using var buffer = array.AsValueEnumerable() + .ToArray(ArrayPool.Shared); + return buffer; + } + + [BenchmarkCategory("Enumerable_Value")] + [Benchmark] + public IMemoryOwner Hyperlinq_Enumerable_ArrayPool_Value() + { + using var buffer = enumerableValue.AsValueEnumerable() + .ToArray(ArrayPool.Shared); + return buffer; + } + + [BenchmarkCategory("Collection_Value")] + [Benchmark] + public IMemoryOwner Hyperlinq_Collection_ArrayPool_Value() + { + using var buffer = collectionValue.AsValueEnumerable() + .ToArray(ArrayPool.Shared); + return buffer; + } + + [BenchmarkCategory("List_Value")] + [Benchmark] + public IMemoryOwner Hyperlinq_List_ArrayPool_Value() + { + using var buffer = listValue + .AsValueEnumerable() + .ToArray(ArrayPool.Shared); + return buffer; + } + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public async ValueTask> Hyperlinq_AsyncEnumerable_ArrayPool_Value() + { + using var buffer = await asyncEnumerableValue + .AsAsyncValueEnumerable() + .ToArrayAsync(ArrayPool.Shared); + return buffer; + } + + [BenchmarkCategory("Enumerable_Reference")] + [Benchmark] + public IMemoryOwner Hyperlinq_Enumerable_ArrayPool_Reference() + { + using var buffer = enumerableReference + .AsValueEnumerable() + .ToArray(ArrayPool.Shared); + return buffer; + } + + [BenchmarkCategory("Collection_Reference")] + [Benchmark] + public IMemoryOwner Hyperlinq_Collection_ArrayPool_Reference() + { + using var buffer = collectionReference + .AsValueEnumerable() + .ToArray(ArrayPool.Shared); + return buffer; + } + + [BenchmarkCategory("List_Reference")] + [Benchmark] + public IMemoryOwner Hyperlinq_List_ArrayPool_Reference() + { + using var buffer = listReference + .AsValueEnumerable() + .ToArray(ArrayPool.Shared); + return buffer; + } + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark] + public async ValueTask> Hyperlinq_AsyncEnumerable_ArrayPool_Reference() + { + using var buffer = await asyncEnumerableReference + .AsAsyncValueEnumerable() + .ToArrayAsync(ArrayPool.Shared); + return buffer; + } } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToListBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToListBenchmarks.cs index 40f4d1cc5..4d990fe0e 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToListBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/ToListBenchmarks.cs @@ -1,7 +1,6 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using StructLinq; -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -15,37 +14,47 @@ public class ToListBenchmarks: RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public List Linq_Array() - => Enumerable.ToList(array); + => array.ToList(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public List Linq_Enumerable_Value() - => Enumerable.ToList(enumerableValue); + => enumerableValue.ToList(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public List Linq_Collection_Value() - => Enumerable.ToList(collectionValue); + => collectionValue.ToList(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public List Linq_List_Value() - => Enumerable.ToList(listValue); + => listValue.ToList(); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public ValueTask> Linq_AsyncEnumerable_Value() + => asyncEnumerableValue.ToListAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public List Linq_Enumerable_Reference() - => Enumerable.ToList(enumerableReference); + => enumerableReference.ToList(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public List Linq_Collection_Reference() - => Enumerable.ToList(collectionReference); + => collectionReference.ToList(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public List Linq_List_Reference() - => Enumerable.ToList(listReference); + => listReference.ToList(); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public ValueTask> Linq_AsyncEnumerable_Reference() + => asyncEnumerableReference.ToListAsync(); // --------------------------------------------------------------------- @@ -103,31 +112,19 @@ public List StructLinq_List_Reference() [BenchmarkCategory("Array")] [Benchmark] public List Hyperlinq_Array() - => array - .ToList(); - - [BenchmarkCategory("Array")] - [Benchmark] - public List Hyperlinq_Span() - => array.AsSpan() - .ToList(); - - [BenchmarkCategory("Array")] - [Benchmark] - public List Hyperlinq_Memory() - => memory.AsValueEnumerable() + => array.AsValueEnumerable() .ToList(); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public List Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .ToList(); [BenchmarkCategory("Collection_Value")] [Benchmark] public List Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .ToList(); [BenchmarkCategory("List_Value")] @@ -141,7 +138,7 @@ public List Hyperlinq_List_Value() [Benchmark] public ValueTask> Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) + .AsAsyncValueEnumerable() .ToListAsync(); [BenchmarkCategory("Enumerable_Reference")] diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereBenchmarks.cs index 91318d825..6d6f34c61 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereBenchmarks.cs @@ -3,6 +3,7 @@ using StructLinq; using System; using System.Linq; +using System.Threading.Tasks; namespace NetFabric.Hyperlinq.Benchmarks { @@ -15,7 +16,7 @@ public class WhereBenchmarks : RandomBenchmarksBase public int Linq_Array() { var sum = 0; - foreach (var item in Enumerable.Where(array, item => (item & 0x01) == 0)) + foreach (var item in array.Where(item => (item & 0x01) == 0)) sum += item; return sum; } @@ -25,7 +26,7 @@ public int Linq_Array() public int Linq_Enumerable_Value() { var sum = 0; - foreach (var item in Enumerable.Where(enumerableValue, item => (item & 0x01) == 0)) + foreach (var item in enumerableValue.Where(item => (item & 0x01) == 0)) sum += item; return sum; } @@ -35,7 +36,7 @@ public int Linq_Enumerable_Value() public int Linq_Collection_Value() { var sum = 0; - foreach (var item in Enumerable.Where(collectionValue, item => (item & 0x01) == 0)) + foreach (var item in collectionValue.Where(item => (item & 0x01) == 0)) sum += item; return sum; } @@ -45,7 +46,17 @@ public int Linq_Collection_Value() public int Linq_List_Value() { var sum = 0; - foreach (var item in Enumerable.Where(listValue, item => (item & 0x01) == 0)) + foreach (var item in listValue.Where(item => (item & 0x01) == 0)) + sum += item; + return sum; + } + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public async ValueTask Linq_AsyncEnumerable_Value() + { + var sum = 0; + await foreach (var item in asyncEnumerableValue.Where(item => (item & 0x01) == 0)) sum += item; return sum; } @@ -55,7 +66,7 @@ public int Linq_List_Value() public int Linq_Enumerable_Reference() { var sum = 0; - foreach (var item in Enumerable.Where(enumerableReference, item => (item & 0x01) == 0)) + foreach (var item in enumerableReference.Where(item => (item & 0x01) == 0)) sum += item; return sum; } @@ -65,7 +76,7 @@ public int Linq_Enumerable_Reference() public int Linq_Collection_Reference() { var sum = 0; - foreach (var item in Enumerable.Where(collectionReference, item => (item & 0x01) == 0)) + foreach (var item in collectionReference.Where(item => (item & 0x01) == 0)) sum += item; return sum; } @@ -75,7 +86,17 @@ public int Linq_Collection_Reference() public int Linq_List_Reference() { var sum = 0; - foreach (var item in Enumerable.Where(listReference, item => (item & 0x01) == 0)) + foreach (var item in listReference.Where(item => (item & 0x01) == 0)) + sum += item; + return sum; + } + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public async ValueTask Linq_AsyncEnumerable_Reference() + { + var sum = 0; + await foreach (var item in asyncEnumerableReference.Where(item => (item & 0x01) == 0)) sum += item; return sum; } @@ -159,7 +180,7 @@ public int StructLinq_List_Reference() public int Hyperlinq_Array() { var sum = 0; - foreach (var item in array.Where(item => (item & 0x01) == 0)) + foreach (var item in array.AsValueEnumerable().Where(item => (item & 0x01) == 0)) sum += item; return sum; } @@ -169,7 +190,7 @@ public int Hyperlinq_Array() public int Hyperlinq_Span() { var sum = 0; - foreach (var item in array.AsSpan().Where(item => (item & 0x01) == 0)) + foreach (var item in array.AsSpan().AsValueEnumerable().Where(item => (item & 0x01) == 0)) sum += item; return sum; } @@ -189,7 +210,7 @@ public int Hyperlinq_Memory() public int Hyperlinq_Enumerable_Value() { var sum = 0; - foreach (var item in EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + foreach (var item in enumerableValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0)) sum += item; return sum; @@ -200,7 +221,7 @@ public int Hyperlinq_Enumerable_Value() public int Hyperlinq_Collection_Value() { var sum = 0; - foreach (var item in ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + foreach (var item in collectionValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0)) sum += item; return sum; @@ -216,6 +237,16 @@ public int Hyperlinq_List_Value() return sum; } + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public async ValueTask Hyperlinq_AsyncEnumerable_Value() + { + var sum = 0; + await foreach (var item in asyncEnumerableValue.AsAsyncValueEnumerable().Where((item, _) => new ValueTask((item & 0x01) == 0))) + sum += item; + return sum; + } + [BenchmarkCategory("Enumerable_Reference")] [Benchmark] public int Hyperlinq_Enumerable_Reference() @@ -245,5 +276,15 @@ public int Hyperlinq_List_Reference() sum += item; return sum; } + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark] + public async ValueTask Hyperlinq_AsyncEnumerable_Reference() + { + var sum = 0; + await foreach (var item in asyncEnumerableReference.AsAsyncValueEnumerable().Where((item, _) => new ValueTask((item & 0x01) == 0))) + sum += item; + return sum; + } } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereCountBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereCountBenchmarks.cs index 4bcd791c3..51cfb5fd4 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereCountBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereCountBenchmarks.cs @@ -14,47 +14,47 @@ public class WhereCountBenchmarks : RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() - => Enumerable.Count(array, item => (item & 0x01) == 0); + => array.Count(item => (item & 0x01) == 0); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Value() - => Enumerable.Count(enumerableValue, item => (item & 0x01) == 0); + => enumerableValue.Count(item => (item & 0x01) == 0); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int Linq_Collection_Value() - => Enumerable.Count(collectionValue, item => (item & 0x01) == 0); + => collectionValue.Count(item => (item & 0x01) == 0); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int Linq_List_Value() - => Enumerable.Count(listValue, item => (item & 0x01) == 0); + => listValue.Count(item => (item & 0x01) == 0); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.CountAsync(asyncEnumerableValue, item => (item & 0x01) == 0); + => asyncEnumerableValue.CountAsync(item => (item & 0x01) == 0); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Reference() - => Enumerable.Count(enumerableReference, item => (item & 0x01) == 0); + => enumerableReference.Count(item => (item & 0x01) == 0); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int Linq_Collection_Reference() - => Enumerable.Count(collectionReference, item => (item & 0x01) == 0); + => collectionReference.Count(item => (item & 0x01) == 0); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int Linq_List_Reference() - => Enumerable.Count(listReference, item => (item & 0x01) == 0); + => listReference.Count(item => (item & 0x01) == 0); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.CountAsync(asyncEnumerableReference, item => (item & 0x01) == 0); + => asyncEnumerableReference.CountAsync(item => (item & 0x01) == 0); // --------------------------------------------------------------------- @@ -119,14 +119,14 @@ public int StructLinq_List_Reference() [BenchmarkCategory("Array")] [Benchmark] public int Hyperlinq_Array() - => array + => array.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .Count(); [BenchmarkCategory("Array")] [Benchmark] public int Hyperlinq_Span() - => array.AsSpan() + => array.AsSpan().AsValueEnumerable() .Where(item => (item & 0x01) == 0) .Count(); @@ -140,14 +140,14 @@ public int Hyperlinq_Memory() [BenchmarkCategory("Enumerable_Value")] [Benchmark] public int Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .Count(); [BenchmarkCategory("Collection_Value")] [Benchmark] public int Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .Count(); @@ -163,8 +163,8 @@ public int Hyperlinq_List_Value() [Benchmark] public ValueTask Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - .Where(item => (item & 0x01) == 0) + .AsAsyncValueEnumerable() + .Where((item, _) => new ValueTask((item & 0x01) == 0)) .CountAsync(); [BenchmarkCategory("Enumerable_Reference")] @@ -196,7 +196,7 @@ public int Hyperlinq_List_Reference() public ValueTask Hyperlinq_AsyncEnumerable_Reference() => asyncEnumerableReference .AsAsyncValueEnumerable() - .Where(item => (item & 0x01) == 0) + .Where((item, _) => new ValueTask((item & 0x01) == 0)) .CountAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereFirstBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereFirstBenchmarks.cs index cb35b385d..08b9a0383 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereFirstBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereFirstBenchmarks.cs @@ -1,7 +1,5 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using StructLinq; -using System; using System.Linq; using System.Threading.Tasks; @@ -9,52 +7,52 @@ namespace NetFabric.Hyperlinq.Benchmarks { [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] [CategoriesColumn] - public class WhereFirstBenchmarks: RandomBenchmarksBase + public class WhereFirstBenchmarks: SequentialBenchmarksBase { [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() - => Enumerable.First(array, item => item == Count - 1); + => array.First(item => item == Count - 1); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Value() - => Enumerable.First(enumerableValue, item => item == Count - 1); + => enumerableValue.First(item => item == Count - 1); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int Linq_Collection_Value() - => Enumerable.First(collectionValue, item => item == Count - 1); + => collectionValue.First(item => item == Count - 1); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int Linq_List_Value() - => Enumerable.First(listValue, item => item == Count - 1); + => listValue.First(item => item == Count - 1); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.FirstAsync(asyncEnumerableValue, item => item == Count - 1); + => asyncEnumerableValue.FirstAsync(item => item == Count - 1); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Reference() - => Enumerable.First(enumerableReference, item => item == Count - 1); + => enumerableReference.First(item => item == Count - 1); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int Linq_Collection_Reference() - => Enumerable.First(collectionReference, item => item == Count - 1); + => collectionReference.First(item => item == Count - 1); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int Linq_List_Reference() - => Enumerable.First(listReference, item => item == Count - 1); + => listReference.First(item => item == Count - 1); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.FirstAsync(asyncEnumerableReference, item => item == Count - 1); + => asyncEnumerableReference.FirstAsync(item => item == Count - 1); // --------------------------------------------------------------------- @@ -65,31 +63,17 @@ public Option Hyperlinq_Array() .Where(item => item == Count - 1) .First(); - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Span() - => array.AsSpan() - .Where(item => item == Count - 1) - .First(); - - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Memory() - => memory.AsValueEnumerable() - .Where(item => item == Count - 1) - .First(); - [BenchmarkCategory("Enumerable_Value")] [Benchmark] public Option Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Where(item => item == Count - 1) .First(); [BenchmarkCategory("Collection_Value")] [Benchmark] public Option Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Where(item => item == Count - 1) .First(); @@ -103,10 +87,10 @@ public Option Hyperlinq_List_Value() [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark] - public ValueTask Hyperlinq_AsyncEnumerable_Value() + public ValueTask> Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - .Where(item => item == Count - 1) + .AsAsyncValueEnumerable() + .Where((item, _) => new ValueTask(item == Count - 1)) .FirstAsync(); [BenchmarkCategory("Enumerable_Reference")] @@ -135,10 +119,10 @@ public Option Hyperlinq_List_Reference() [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark] - public ValueTask Hyperlinq_AsyncEnumerable_Reference() + public ValueTask> Hyperlinq_AsyncEnumerable_Reference() => asyncEnumerableReference .AsAsyncValueEnumerable() - .Where(item => item == Count - 1) + .Where((item, _) => new ValueTask(item == Count - 1)) .FirstAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectBenchmarks.cs index e78f79b0b..161c85fa9 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectBenchmarks.cs @@ -3,6 +3,7 @@ using StructLinq; using System; using System.Linq; +using System.Threading.Tasks; namespace NetFabric.Hyperlinq.Benchmarks { @@ -15,7 +16,9 @@ public class WhereSelectBenchmarks: RandomBenchmarksBase public int Linq_Array() { var sum = 0; - foreach (var item in Enumerable.Where(array, item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in array + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -25,7 +28,9 @@ public int Linq_Array() public int Linq_Enumerable_Value() { var sum = 0; - foreach (var item in Enumerable.Where(enumerableValue, item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in enumerableValue + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -35,7 +40,9 @@ public int Linq_Enumerable_Value() public int Linq_Collection_Value() { var sum = 0; - foreach (var item in Enumerable.Where(collectionValue, item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in collectionValue + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -45,7 +52,21 @@ public int Linq_Collection_Value() public int Linq_List_Value() { var sum = 0; - foreach (var item in Enumerable.Where(listValue, item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in listValue + .Where(item => (item & 0x01) == 0) + .Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public async ValueTask Linq_AsyncEnumerable_Value() + { + var sum = 0; + await foreach (var item in asyncEnumerableValue + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -55,7 +76,9 @@ public int Linq_List_Value() public int Linq_Enumerable_Reference() { var sum = 0; - foreach (var item in Enumerable.Where(enumerableReference, item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in enumerableReference + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -65,7 +88,9 @@ public int Linq_Enumerable_Reference() public int Linq_Collection_Reference() { var sum = 0; - foreach (var item in Enumerable.Where(collectionReference, item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in collectionReference + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -75,7 +100,21 @@ public int Linq_Collection_Reference() public int Linq_List_Reference() { var sum = 0; - foreach (var item in Enumerable.Where(listReference, item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in listReference + .Where(item => (item & 0x01) == 0) + .Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public async ValueTask Linq_AsyncEnumerable_Reference() + { + var sum = 0; + await foreach (var item in asyncEnumerableReference + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -87,7 +126,9 @@ public int Linq_List_Reference() public int StructLinq_Array() { var sum = 0; - foreach (var item in array.ToStructEnumerable().Where(item => (item & 0x01) == 0, x => x).Select(item => item, x => x)) + foreach (var item in array.ToStructEnumerable() + .Where(item => (item & 0x01) == 0, x => x) + .Select(item => item, x => x)) sum += item; return sum; } @@ -97,7 +138,9 @@ public int StructLinq_Array() public int StructLinq_Enumerable_Value() { var sum = 0; - foreach (var item in enumerableValue.ToStructEnumerable().Where(item => (item & 0x01) == 0, x => x).Select(item => item, x => x)) + foreach (var item in enumerableValue.ToStructEnumerable() + .Where(item => (item & 0x01) == 0, x => x) + .Select(item => item, x => x)) sum += item; return sum; } @@ -107,7 +150,9 @@ public int StructLinq_Enumerable_Value() public int StructLinq_Collection_Value() { var sum = 0; - foreach (var item in collectionValue.ToStructEnumerable().Where(item => (item & 0x01) == 0, x => x).Select(item => item, x => x)) + foreach (var item in collectionValue.ToStructEnumerable() + .Where(item => (item & 0x01) == 0, x => x) + .Select(item => item, x => x)) sum += item; return sum; } @@ -117,7 +162,9 @@ public int StructLinq_Collection_Value() public int StructLinq_List_Value() { var sum = 0; - foreach (var item in listValue.ToStructEnumerable().Where(item => (item & 0x01) == 0, x => x).Select(item => item, x => x)) + foreach (var item in listValue.ToStructEnumerable() + .Where(item => (item & 0x01) == 0, x => x) + .Select(item => item, x => x)) sum += item; return sum; } @@ -127,7 +174,9 @@ public int StructLinq_List_Value() public int StructLinq_Enumerable_Reference() { var sum = 0; - foreach (var item in enumerableReference.ToStructEnumerable().Where(item => (item & 0x01) == 0, x => x).Select(item => item, x => x)) + foreach (var item in enumerableReference.ToStructEnumerable() + .Where(item => (item & 0x01) == 0, x => x) + .Select(item => item, x => x)) sum += item; return sum; } @@ -137,7 +186,9 @@ public int StructLinq_Enumerable_Reference() public int StructLinq_Collection_Reference() { var sum = 0; - foreach (var item in collectionReference.ToStructEnumerable().Where(item => (item & 0x01) == 0, x => x).Select(item => item, x => x)) + foreach (var item in collectionReference.ToStructEnumerable() + .Where(item => (item & 0x01) == 0, x => x) + .Select(item => item, x => x)) sum += item; return sum; } @@ -147,7 +198,9 @@ public int StructLinq_Collection_Reference() public int StructLinq_List_Reference() { var sum = 0; - foreach (var item in listReference.ToStructEnumerable().Where(item => (item & 0x01) == 0, x => x).Select(item => item, x => x)) + foreach (var item in listReference.ToStructEnumerable() + .Where(item => (item & 0x01) == 0, x => x) + .Select(item => item, x => x)) sum += item; return sum; } @@ -159,7 +212,9 @@ public int StructLinq_List_Reference() public int Hyperlinq_Array() { var sum = 0; - foreach (var item in array.Where(item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in array.AsValueEnumerable() + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -169,7 +224,9 @@ public int Hyperlinq_Array() public int Hyperlinq_Span() { var sum = 0; - foreach (var item in array.AsSpan().Where(item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in array.AsSpan().AsValueEnumerable() + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -179,7 +236,9 @@ public int Hyperlinq_Span() public int Hyperlinq_Memory() { var sum = 0; - foreach (var item in memory.AsValueEnumerable().Where(item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in memory.AsValueEnumerable() + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -189,7 +248,7 @@ public int Hyperlinq_Memory() public int Hyperlinq_Enumerable_Value() { var sum = 0; - foreach (var item in EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + foreach (var item in enumerableValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .Select(item => item)) sum += item; @@ -201,7 +260,7 @@ public int Hyperlinq_Enumerable_Value() public int Hyperlinq_Collection_Value() { var sum = 0; - foreach (var item in ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + foreach (var item in collectionValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .Select(item => item)) sum += item; @@ -213,7 +272,21 @@ public int Hyperlinq_Collection_Value() public int Hyperlinq_List_Value() { var sum = 0; - foreach (var item in listValue.AsValueEnumerable().Where(item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in listValue.AsValueEnumerable() + .Where(item => (item & 0x01) == 0) + .Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public async ValueTask Hyperlinq_AsyncEnumerable_Value() + { + var sum = 0; + await foreach (var item in asyncEnumerableValue.AsAsyncValueEnumerable() + .Where((item, _) => new ValueTask((item & 0x01) == 0)) + .Select((item, _) => new ValueTask(item))) sum += item; return sum; } @@ -223,7 +296,9 @@ public int Hyperlinq_List_Value() public int Hyperlinq_Enumerable_Reference() { var sum = 0; - foreach (var item in enumerableReference.AsValueEnumerable().Where(item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in enumerableReference.AsValueEnumerable() + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -233,7 +308,9 @@ public int Hyperlinq_Enumerable_Reference() public int Hyperlinq_Collection_Reference() { var sum = 0; - foreach (var item in collectionReference.AsValueEnumerable().Where(item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in collectionReference.AsValueEnumerable() + .Where(item => (item & 0x01) == 0) + .Select(item => item)) sum += item; return sum; } @@ -243,7 +320,21 @@ public int Hyperlinq_Collection_Reference() public int Hyperlinq_List_Reference() { var sum = 0; - foreach (var item in listReference.AsValueEnumerable().Where(item => (item & 0x01) == 0).Select(item => item)) + foreach (var item in listReference.AsValueEnumerable() + .Where(item => (item & 0x01) == 0) + .Select(item => item)) + sum += item; + return sum; + } + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark] + public async ValueTask Hyperlinq_AsyncEnumerable_Reference() + { + var sum = 0; + await foreach (var item in asyncEnumerableReference.AsAsyncValueEnumerable() + .Where((item, _) => new ValueTask((item & 0x01) == 0)) + .Select((item, _) => new ValueTask(item))) sum += item; return sum; } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectCountBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectCountBenchmarks.cs index 32c13291e..4a47d792c 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectCountBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSelectCountBenchmarks.cs @@ -1,6 +1,7 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using System; +using System.Linq; +using System.Threading.Tasks; namespace NetFabric.Hyperlinq.Benchmarks { @@ -11,74 +12,62 @@ public class WhereSelectCountBenchmarks : RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() - => System.Linq.Enumerable.Count( - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(array, item => (item & 0x01) == 0), item => item)); + => array.Where(item => (item & 0x01) == 0).Select(item => item).Count(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Value() - => System.Linq.Enumerable.Count( - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(enumerableValue, item => (item & 0x01) == 0), item => item)); + => enumerableValue.Where(item => (item & 0x01) == 0).Select(item => item).Count(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int Linq_Collection_Value() - => System.Linq.Enumerable.Count( - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(collectionValue, item => (item & 0x01) == 0), item => item)); + => collectionValue.Where(item => (item & 0x01) == 0).Select(item => item).Count(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int Linq_List_Value() - => System.Linq.Enumerable.Count( - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(listValue, item => (item & 0x01) == 0), item => item)); + => listValue.Where(item => (item & 0x01) == 0).Select(item => item).Count(); + + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Value() + => asyncEnumerableValue.Where(item => (item & 0x01) == 0).Select(item => item).CountAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Reference() - => System.Linq.Enumerable.Count( - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(enumerableReference, item => (item & 0x01) == 0), item => item)); + => enumerableReference.Where(item => (item & 0x01) == 0).Select(item => item).Count(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int Linq_Collection_Reference() - => System.Linq.Enumerable.Count( - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(collectionReference, item => (item & 0x01) == 0), item => item)); + => collectionReference.Where(item => (item & 0x01) == 0).Select(item => item).Count(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int Linq_List_Reference() - => System.Linq.Enumerable.Count( - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(listReference, item => (item & 0x01) == 0), item => item)); + => listReference.Where(item => (item & 0x01) == 0).Select(item => item).Count(); - [BenchmarkCategory("Array")] - [Benchmark] - public int Hyperlinq_Array() - => array.AsValueEnumerable().Where(item => (item & 0x01) == 0).Select(item => item).Count(); + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark(Baseline = true)] + public ValueTask Linq_AsyncEnumerable_Reference() + => asyncEnumerableReference.Where(item => (item & 0x01) == 0).Select(item => item).CountAsync(); - [BenchmarkCategory("Array")] - [Benchmark] - public int Hyperlinq_Span() - => array.AsSpan().Where(item => (item & 0x01) == 0).Select(item => item).Count(); + // --------------------------------------------------------------------- [BenchmarkCategory("Array")] [Benchmark] - public int Hyperlinq_Memory() - => memory.AsValueEnumerable().Where(item => (item & 0x01) == 0).Select(item => item).Count(); + public int Hyperlinq_Array() + => array.AsValueEnumerable().Where(item => (item & 0x01) == 0).Select(item => item).Count(); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public int Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .Select(item => item) .Count(); @@ -86,7 +75,7 @@ public int Hyperlinq_Enumerable_Value() [BenchmarkCategory("Collection_Value")] [Benchmark] public int Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .Select(item => item) .Count(); @@ -101,6 +90,15 @@ public int Hyperlinq_List_Value() .Select(item => item) .Count(); + [BenchmarkCategory("AsyncEnumerable_Value")] + [Benchmark] + public ValueTask Hyperlinq_AsyncEnumerable_Value() + => asyncEnumerableValue + .AsAsyncValueEnumerable() + .Where((item, _) => new ValueTask((item & 0x01) == 0)) + .Select((item, _) => new ValueTask(item)) + .CountAsync(); + [BenchmarkCategory("Enumerable_Reference")] [Benchmark] public int Hyperlinq_Enumerable_Reference() @@ -127,5 +125,14 @@ public int Hyperlinq_List_Reference() .Where(item => (item & 0x01) == 0) .Select(item => item) .Count(); + + [BenchmarkCategory("AsyncEnumerable_Reference")] + [Benchmark] + public ValueTask Hyperlinq_AsyncEnumerable_Reference() + => asyncEnumerableReference + .AsAsyncValueEnumerable() + .Where((item, _) => new ValueTask((item & 0x01) == 0)) + .Select((item, _) => new ValueTask(item)) + .CountAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSingleBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSingleBenchmarks.cs index a1453a9f4..2f03107d3 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSingleBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereSingleBenchmarks.cs @@ -1,7 +1,5 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -using StructLinq; -using System; using System.Linq; using System.Threading.Tasks; @@ -9,52 +7,52 @@ namespace NetFabric.Hyperlinq.Benchmarks { [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] [CategoriesColumn] - public class WhereSingleBenchmarks: RandomBenchmarksBase + public class WhereSingleBenchmarks: SequentialBenchmarksBase { [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int Linq_Array() - => Enumerable.Single(array, item => item == Count - 1); + => array.Single(item => item == Count - 1); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Value() - => Enumerable.Single(enumerableValue, item => item == Count - 1); + => enumerableValue.Single(item => item == Count - 1); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int Linq_Collection_Value() - => Enumerable.Single(collectionValue, item => item == Count - 1); + => collectionValue.Single(item => item == Count - 1); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int Linq_List_Value() - => Enumerable.Single(listValue, item => item == Count - 1); + => listValue.Single(item => item == Count - 1); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.SingleAsync(asyncEnumerableValue, item => item == Count - 1); + => asyncEnumerableValue.SingleAsync(item => item == Count - 1); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int Linq_Enumerable_Reference() - => Enumerable.Single(enumerableReference, item => item == Count - 1); + => enumerableReference.Single(item => item == Count - 1); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int Linq_Collection_Reference() - => Enumerable.Single(collectionReference, item => item == Count - 1); + => collectionReference.Single(item => item == Count - 1); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int Linq_List_Reference() - => Enumerable.Single(listReference, item => item == Count - 1); + => listReference.Single(item => item == Count - 1); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.SingleAsync(asyncEnumerableReference, item => item == Count - 1); + => asyncEnumerableReference.SingleAsync(item => item == Count - 1); // --------------------------------------------------------------------- @@ -65,31 +63,17 @@ public Option Hyperlinq_Array() .Where(item => item == Count - 1) .Single(); - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Span() - => array.AsSpan() - .Where(item => item == Count - 1) - .Single(); - - [BenchmarkCategory("Array")] - [Benchmark] - public Option Hyperlinq_Memory() - => memory.AsValueEnumerable() - .Where(item => item == Count - 1) - .Single(); - [BenchmarkCategory("Enumerable_Value")] [Benchmark] public Option Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Where(item => item == Count - 1) .Single(); [BenchmarkCategory("Collection_Value")] [Benchmark] public Option Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Where(item => item == Count - 1) .Single(); @@ -101,13 +85,13 @@ public Option Hyperlinq_List_Value() .Where(item => item == Count - 1) .Single(); - [BenchmarkCategory("AsyncEnumerable_Value")] - [Benchmark] - public ValueTask Hyperlinq_AsyncEnumerable_Value() - => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - .Where(item => item == Count - 1) - .SingleAsync(); + // [BenchmarkCategory("AsyncEnumerable_Value")] + // [Benchmark] + // public ValueTask> Hyperlinq_AsyncEnumerable_Value() + // => asyncEnumerableValue + // .AsAsyncValueEnumerable() + // .Where((item, _) => new ValueTask(item == Count - 1)) + // .SingleAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark] @@ -133,12 +117,12 @@ public Option Hyperlinq_List_Reference() .Where(item => item == Count - 1) .Single(); - [BenchmarkCategory("AsyncEnumerable_Reference")] - [Benchmark] - public ValueTask Hyperlinq_AsyncEnumerable_Reference() - => asyncEnumerableReference - .AsAsyncValueEnumerable() - .Where(item => item == Count - 1) - .SingleAsync(); + // [BenchmarkCategory("AsyncEnumerable_Reference")] + // [Benchmark] + // public ValueTask> Hyperlinq_AsyncEnumerable_Reference() + // => asyncEnumerableReference + // .AsAsyncValueEnumerable() + // .Where((item, _) => new ValueTask(item == Count - 1)) + // .SingleAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToArrayBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToArrayBenchmarks.cs index 6232152bf..1136ef872 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToArrayBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToArrayBenchmarks.cs @@ -1,7 +1,6 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using StructLinq; -using System; using System.Linq; using System.Threading.Tasks; @@ -14,55 +13,55 @@ public class WhereToArrayBenchmarks: RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public int[] Linq_Array() - => Enumerable.Where(array, item => (item & 0x01) == 0) + => array.Where(item => (item & 0x01) == 0) .ToArray(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public int[] Linq_Enumerable_Value() - => Enumerable.Where(enumerableValue, item => (item & 0x01) == 0) + => enumerableValue.Where(item => (item & 0x01) == 0) .ToArray(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public int[] Linq_Collection_Value() - => Enumerable.Where(collectionValue, item => (item & 0x01) == 0) + => collectionValue.Where(item => (item & 0x01) == 0) .ToArray(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public int[] Linq_List_Value() - => Enumerable.Where(listValue, item => (item & 0x01) == 0) + => listValue.Where(item => (item & 0x01) == 0) .ToArray(); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Value() - => AsyncEnumerable.Where(asyncEnumerableValue, item => (item & 0x01) == 0) + => asyncEnumerableValue.Where(item => (item & 0x01) == 0) .ToArrayAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public int[] Linq_Enumerable_Reference() - => Enumerable.Where(enumerableReference, item => (item & 0x01) == 0) + => enumerableReference.Where(item => (item & 0x01) == 0) .ToArray(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public int[] Linq_Collection_Reference() - => Enumerable.Where(collectionReference, item => (item & 0x01) == 0) + => collectionReference.Where(item => (item & 0x01) == 0) .ToArray(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public int[] Linq_List_Reference() - => Enumerable.Where(listReference, item => (item & 0x01) == 0) + => listReference.Where(item => (item & 0x01) == 0) .ToArray(); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.Where(asyncEnumerableReference, item => (item & 0x01) == 0) + => asyncEnumerableReference.Where(item => (item & 0x01) == 0) .ToArrayAsync(); // --------------------------------------------------------------------- @@ -128,35 +127,21 @@ public int[] StructLinq_List_Reference() [BenchmarkCategory("Array")] [Benchmark] public int[] Hyperlinq_Array() - => array - .Where(item => (item & 0x01) == 0) - .ToArray(); - - [BenchmarkCategory("Array")] - [Benchmark] - public int[] Hyperlinq_Span() - => array.AsSpan() - .Where(item => (item & 0x01) == 0) - .ToArray(); - - [BenchmarkCategory("Array")] - [Benchmark] - public int[] Hyperlinq_Memory() - => memory.AsValueEnumerable() + => array.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .ToArray(); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public int[] Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .ToArray(); [BenchmarkCategory("Collection_Value")] [Benchmark] public int[] Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .ToArray(); @@ -172,8 +157,8 @@ public int[] Hyperlinq_List_Value() [Benchmark] public ValueTask Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - .Where(item => (item & 0x01) == 0) + .AsAsyncValueEnumerable() + .Where((item, _) => new ValueTask((item & 0x01) == 0)) .ToArrayAsync(); [BenchmarkCategory("Enumerable_Reference")] @@ -205,7 +190,7 @@ public int[] Hyperlinq_List_Reference() public ValueTask Hyperlinq_AsyncEnumerable_Reference() => asyncEnumerableReference .AsAsyncValueEnumerable() - .Where(item => (item & 0x01) == 0) + .Where((item, _) => new ValueTask((item & 0x01) == 0)) .ToArrayAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToListBenchmarks.cs b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToListBenchmarks.cs index 27db6f63e..497091b29 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToListBenchmarks.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Benchmarks/WhereToListBenchmarks.cs @@ -1,7 +1,6 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using StructLinq; -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -15,55 +14,55 @@ public class WhereToListBenchmarks: RandomBenchmarksBase [BenchmarkCategory("Array")] [Benchmark(Baseline = true)] public List Linq_Array() - => Enumerable.Where(array, item => (item & 0x01) == 0) + => array.Where(item => (item & 0x01) == 0) .ToList(); [BenchmarkCategory("Enumerable_Value")] [Benchmark(Baseline = true)] public List Linq_Enumerable_Value() - => Enumerable.Where(enumerableValue, item => (item & 0x01) == 0) + => enumerableValue.Where(item => (item & 0x01) == 0) .ToList(); [BenchmarkCategory("Collection_Value")] [Benchmark(Baseline = true)] public List Linq_Collection_Value() - => Enumerable.Where(collectionValue, item => (item & 0x01) == 0) + => collectionValue.Where(item => (item & 0x01) == 0) .ToList(); [BenchmarkCategory("List_Value")] [Benchmark(Baseline = true)] public List Linq_List_Value() - => Enumerable.Where(listValue, item => (item & 0x01) == 0) + => listValue.Where(item => (item & 0x01) == 0) .ToList(); [BenchmarkCategory("AsyncEnumerable_Value")] [Benchmark(Baseline = true)] public ValueTask> Linq_AsyncEnumerable_Value() - => AsyncEnumerable.Where(asyncEnumerableValue, item => (item & 0x01) == 0) + => asyncEnumerableValue.Where(item => (item & 0x01) == 0) .ToListAsync(); [BenchmarkCategory("Enumerable_Reference")] [Benchmark(Baseline = true)] public List Linq_Enumerable_Reference() - => Enumerable.Where(enumerableReference, item => (item & 0x01) == 0) + => enumerableReference.Where(item => (item & 0x01) == 0) .ToList(); [BenchmarkCategory("Collection_Reference")] [Benchmark(Baseline = true)] public List Linq_Collection_Reference() - => Enumerable.Where(collectionReference, item => (item & 0x01) == 0) + => collectionReference.Where(item => (item & 0x01) == 0) .ToList(); [BenchmarkCategory("List_Reference")] [Benchmark(Baseline = true)] public List Linq_List_Reference() - => Enumerable.Where(listReference, item => (item & 0x01) == 0) + => listReference.Where(item => (item & 0x01) == 0) .ToList(); [BenchmarkCategory("AsyncEnumerable_Reference")] [Benchmark(Baseline = true)] public ValueTask> Linq_AsyncEnumerable_Reference() - => AsyncEnumerable.Where(asyncEnumerableReference, item => (item & 0x01) == 0) + => asyncEnumerableReference.Where(item => (item & 0x01) == 0) .ToListAsync(); // --------------------------------------------------------------------- @@ -129,35 +128,21 @@ public List StructLinq_List_Reference() [BenchmarkCategory("Array")] [Benchmark] public List Hyperlinq_Array() - => array - .Where(item => (item & 0x01) == 0) - .ToList(); - - [BenchmarkCategory("Array")] - [Benchmark] - public List Hyperlinq_Span() - => array.AsSpan() - .Where(item => (item & 0x01) == 0) - .ToList(); - - [BenchmarkCategory("Array")] - [Benchmark] - public List Hyperlinq_Memory() - => memory.AsValueEnumerable() + => array.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .ToList(); [BenchmarkCategory("Enumerable_Value")] [Benchmark] public List Hyperlinq_Enumerable_Value() - => EnumerableExtensions.AsValueEnumerable(enumerableValue, enumerable => enumerable.GetEnumerator()) + => enumerableValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .ToList(); [BenchmarkCategory("Collection_Value")] [Benchmark] public List Hyperlinq_Collection_Value() - => ReadOnlyCollectionExtensions.AsValueEnumerable(collectionValue, enumerable => enumerable.GetEnumerator()) + => collectionValue.AsValueEnumerable() .Where(item => (item & 0x01) == 0) .ToList(); @@ -173,8 +158,8 @@ public List Hyperlinq_List_Value() [Benchmark] public ValueTask> Hyperlinq_AsyncEnumerable_Value() => asyncEnumerableValue - .AsAsyncValueEnumerable((enumerable, cancellationToke) => enumerable.GetAsyncEnumerator(cancellationToke)) - .Where(item => (item & 0x01) == 0) + .AsAsyncValueEnumerable() + .Where((item, _) => new ValueTask((item & 0x01) == 0)) .ToListAsync(); [BenchmarkCategory("Enumerable_Reference")] @@ -206,7 +191,7 @@ public List Hyperlinq_List_Reference() public ValueTask> Hyperlinq_AsyncEnumerable_Reference() => asyncEnumerableReference .AsAsyncValueEnumerable() - .Where(item => (item & 0x01) == 0) + .Where((item, _) => new ValueTask((item & 0x01) == 0)) .ToListAsync(); } } diff --git a/NetFabric.Hyperlinq.Benchmarks/BenchmarksBase.cs b/NetFabric.Hyperlinq.Benchmarks/BenchmarksBase.cs index 0d9e039b9..d73154b8b 100644 --- a/NetFabric.Hyperlinq.Benchmarks/BenchmarksBase.cs +++ b/NetFabric.Hyperlinq.Benchmarks/BenchmarksBase.cs @@ -2,36 +2,27 @@ using BenchmarkDotNet.Jobs; using System; using System.Collections.Generic; -using System.Collections.Specialized; namespace NetFabric.Hyperlinq.Benchmarks { - //[SimpleJob(RuntimeMoniker.Net48, baseline: true)] - //[SimpleJob(RuntimeMoniker.NetCoreApp21)] - //[SimpleJob(RuntimeMoniker.NetCoreApp31)] - [SimpleJob(RuntimeMoniker.NetCoreApp50)] - [MemoryDiagnoser] public abstract class BenchmarksBase { protected const int seed = 42; - + protected int[] array; protected ReadOnlyMemory memory; - protected IEnumerable linqRange; - protected ValueEnumerable.RangeEnumerable hyperlinqRange; - protected IEnumerable enumerableReference; - protected TestEnumerable.Enumerable enumerableValue; + protected Wrap.EnumerableWrapper enumerableValue; protected IReadOnlyCollection collectionReference; - protected TestCollection.Enumerable collectionValue; + protected Wrap.CollectionWrapper collectionValue; protected IReadOnlyList listReference; - protected TestList.Enumerable listValue; + protected Wrap.ListWrapper listValue; protected IAsyncEnumerable asyncEnumerableReference; - protected TestAsyncEnumerable.Enumerable asyncEnumerableValue; + protected Wrap.AsyncEnumerableWrapper asyncEnumerableValue; [GlobalSetup] public abstract void GlobalSetup(); @@ -41,17 +32,10 @@ protected void Initialize(int[] array) this.array = array; memory = array.AsMemory(); - enumerableReference = TestEnumerable.ReferenceType(array); - enumerableValue = TestEnumerable.ValueType(array); - - collectionReference = TestCollection.ReferenceType(array); - collectionValue = TestCollection.ValueType(array); - - listReference = TestList.ReferenceType(array); - listValue = TestList.ValueType(array); - - asyncEnumerableReference = TestAsyncEnumerable.ReferenceType(array); - asyncEnumerableValue = TestAsyncEnumerable.ValueType(array); + enumerableReference = enumerableValue = Wrap.AsEnumerable(array); + collectionReference = collectionValue = Wrap.AsCollection(array); + listReference = listValue = Wrap.AsList(array); + asyncEnumerableReference = asyncEnumerableValue = Wrap.AsAsyncEnumerable(array); } } } diff --git a/NetFabric.Hyperlinq.Benchmarks/NetFabric.Hyperlinq.Benchmarks.csproj b/NetFabric.Hyperlinq.Benchmarks/NetFabric.Hyperlinq.Benchmarks.csproj index 7cd5c5a5e..88176afb2 100644 --- a/NetFabric.Hyperlinq.Benchmarks/NetFabric.Hyperlinq.Benchmarks.csproj +++ b/NetFabric.Hyperlinq.Benchmarks/NetFabric.Hyperlinq.Benchmarks.csproj @@ -1,25 +1,21 @@  Exe - net5.0 + net6.0 false - true - - - - AnyCPU - pdbonly - true + Release + false + - + - + diff --git a/NetFabric.Hyperlinq.Benchmarks/Program.cs b/NetFabric.Hyperlinq.Benchmarks/Program.cs index b65d028a2..719f44b07 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Program.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Program.cs @@ -1,12 +1,18 @@ -using System; +using BenchmarkDotNet.Columns; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Environments; +using System; using System.IO; using System.Linq; using System.Reflection; using System.Text; using BenchmarkDotNet.Exporters; +using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Loggers; using BenchmarkDotNet.Reports; using BenchmarkDotNet.Running; +using BenchmarkDotNet.Validators; namespace NetFabric.Hyperlinq.Benchmarks { @@ -14,7 +20,18 @@ class Program { static void Main(string[] args) { - foreach (var summary in BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args)) + var config = DefaultConfig.Instance + .WithSummaryStyle(SummaryStyle.Default.WithRatioStyle(RatioStyle.Trend)) + .AddJob(Job.Default + .WithRuntime(CoreRuntime.Core60) + .WithEnvironmentVariables( + new EnvironmentVariable("COMPlus_ReadyToRun", "0"), + new EnvironmentVariable("COMPlus_TC_QuickJitForLoops", "1"), + new EnvironmentVariable("COMPlus_TieredPGO", "1")) + .WithId(".NET 6 PGO")) + .AddDiagnoser(MemoryDiagnoser.Default); + + foreach (var summary in BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config)) SaveSummary(summary); } @@ -75,22 +92,22 @@ static void SaveSummary(Summary summary) } static string GetInformationalVersion(Assembly assembly) - => GetCustomAttribute(assembly)?.InformationalVersion.Split('+')[0]; + => GetCustomAttribute(assembly)?.InformationalVersion.Split('+')[0] ?? ""; - static T GetCustomAttribute(Assembly assembly) where T : Attribute - => (T)Attribute.GetCustomAttribute(assembly, typeof(T), false); + static T? GetCustomAttribute(Assembly assembly) where T : Attribute + => (T?)Attribute.GetCustomAttribute(assembly, typeof(T), false); - static Type GetTargetType(Summary summary) + static Type? GetTargetType(Summary summary) { var targetTypes = summary.BenchmarksCases.Select(i => i.Descriptor.Type).Distinct().ToList(); return targetTypes.Count == 1 ? targetTypes[0] : null; } - static string GetSolutionDirectory() + static string? GetSolutionDirectory() { - var dir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + var dir = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); - while (!string.IsNullOrEmpty(dir)) + while (dir is not null and { Length: not 0 }) { if (Directory.EnumerateFiles(dir, "*.sln", SearchOption.TopDirectoryOnly).Any()) return dir; @@ -98,7 +115,7 @@ static string GetSolutionDirectory() dir = Path.GetDirectoryName(dir); } - return null; + return default; } } } diff --git a/NetFabric.Hyperlinq.Benchmarks/RandomBenchmarksBase.cs b/NetFabric.Hyperlinq.Benchmarks/RandomBenchmarksBase.cs index 47739b1b1..2153ed7cf 100644 --- a/NetFabric.Hyperlinq.Benchmarks/RandomBenchmarksBase.cs +++ b/NetFabric.Hyperlinq.Benchmarks/RandomBenchmarksBase.cs @@ -2,6 +2,7 @@ { public abstract class RandomBenchmarksBase : CountBenchmarksBase { + public override void GlobalSetup() => Initialize(Utils.GetRandomValues(seed, Count)); } diff --git a/NetFabric.Hyperlinq.Benchmarks/SequentialBenchmarksBase.cs b/NetFabric.Hyperlinq.Benchmarks/SequentialBenchmarksBase.cs index ede6ba87b..f9787162d 100644 --- a/NetFabric.Hyperlinq.Benchmarks/SequentialBenchmarksBase.cs +++ b/NetFabric.Hyperlinq.Benchmarks/SequentialBenchmarksBase.cs @@ -1,6 +1,4 @@ -using BenchmarkDotNet.Attributes; - -namespace NetFabric.Hyperlinq.Benchmarks +namespace NetFabric.Hyperlinq.Benchmarks { public abstract class SequentialBenchmarksBase : CountBenchmarksBase { diff --git a/NetFabric.Hyperlinq.Benchmarks/SingleBenchmarksBase.cs b/NetFabric.Hyperlinq.Benchmarks/SingleBenchmarksBase.cs index c5edfd688..8ba532dac 100644 --- a/NetFabric.Hyperlinq.Benchmarks/SingleBenchmarksBase.cs +++ b/NetFabric.Hyperlinq.Benchmarks/SingleBenchmarksBase.cs @@ -4,9 +4,6 @@ namespace NetFabric.Hyperlinq.Benchmarks { public abstract class SingleBenchmarksBase : BenchmarksBase { - [Params(1)] - public int Count { get; set; } - public override void GlobalSetup() => Initialize(new[] { 42 }); } diff --git a/NetFabric.Hyperlinq.Benchmarks/Utils/TestAsyncEnumerable.cs b/NetFabric.Hyperlinq.Benchmarks/Utils/TestAsyncEnumerable.cs deleted file mode 100644 index c96789a85..000000000 --- a/NetFabric.Hyperlinq.Benchmarks/Utils/TestAsyncEnumerable.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace NetFabric.Hyperlinq.Benchmarks -{ - public static class TestAsyncEnumerable - { - - public static Enumerable ValueType(int[] array) - => new Enumerable(array); - - public static IAsyncEnumerable ReferenceType(int[] array) - => new ReferenceEnumerable(array); - - public class Enumerable : IAsyncEnumerable - { - readonly int[] array; - - public Enumerable(int[] array) - => this.array = array; - - public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - => new Enumerator(array, cancellationToken); - IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) - => new Enumerator(array, cancellationToken); - - public struct Enumerator : IAsyncEnumerator - { - readonly int[] array; - readonly CancellationToken cancellationToken; - int index; - - public Enumerator(int[] array, CancellationToken cancellationToken) - { - this.array = array; - this.cancellationToken = cancellationToken; - index = -1; - } - - public int Current => array[index]; - - public ValueTask MoveNextAsync() - { - cancellationToken.ThrowIfCancellationRequested(); - return new ValueTask(++index < array.Length); - } - - public ValueTask DisposeAsync() - => default; - } - } - - class ReferenceEnumerable : IAsyncEnumerable - { - readonly int[] array; - - public ReferenceEnumerable(int[] array) - => this.array = array; - - public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken) - => new Enumerator(array, cancellationToken); - - class Enumerator : IAsyncEnumerator - { - readonly int[] array; - readonly CancellationToken cancellationToken; - int index; - - public Enumerator(int[] array, CancellationToken cancellationToken) - { - this.array = array; - this.cancellationToken = cancellationToken; - index = -1; - } - - public int Current => array[index]; - - public ValueTask MoveNextAsync() - { - cancellationToken.ThrowIfCancellationRequested(); - return new ValueTask(++index < array.Length); - } - - public ValueTask DisposeAsync() - => default; - } - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Benchmarks/Utils/TestCollection.cs b/NetFabric.Hyperlinq.Benchmarks/Utils/TestCollection.cs deleted file mode 100644 index 4d7637a40..000000000 --- a/NetFabric.Hyperlinq.Benchmarks/Utils/TestCollection.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq.Benchmarks -{ - public static class TestCollection - { - public static Enumerable ValueType(int[] array) - => new Enumerable(array); - - public static IReadOnlyCollection ReferenceType(int[] array) - => new EnumerableReferenceType(array); - - public class Enumerable : IReadOnlyCollection, ICollection - { - readonly int[] array; - - public Enumerable(int[] array) - => this.array = array; - - public int Count => array.Length; - - public bool IsReadOnly => true; - - public void Add(int item) => throw new NotImplementedException(); - public bool Remove(int item) => throw new NotImplementedException(); - public void Clear() => throw new NotImplementedException(); - - public bool Contains(int item) - => ((IList)array).Contains(item); - - public void CopyTo(int[] array, int arrayIndex) - => this.array.CopyTo(array, arrayIndex); - - public Enumerator GetEnumerator() - => new Enumerator(array); - IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(array); - IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(array); - - public struct Enumerator : IEnumerator - { - readonly int[] array; - int index; - - public Enumerator(int[] array) - { - this.array = array; - index = -1; - } - - public int Current => array[index]; - object IEnumerator.Current => array[index]; - - public bool MoveNext() => ++index < array.Length; - - public void Reset() => throw new NotSupportedException(); - - public void Dispose() { } - } - } - -#pragma warning disable HLQ006 // GetEnumerator() or GetAsyncEnumerator() should return a value type. - - class EnumerableReferenceType : IReadOnlyCollection, ICollection - { - readonly int[] array; - - public EnumerableReferenceType(int[] array) - => this.array = array; - - public int Count => array.Length; - - public bool IsReadOnly => true; - - public void Add(int item) => throw new NotImplementedException(); - public bool Remove(int item) => throw new NotImplementedException(); - public void Clear() => throw new NotImplementedException(); - - public bool Contains(int item) - => ((IList)array).Contains(item); - - public void CopyTo(int[] array, int arrayIndex) - => this.array.CopyTo(array, arrayIndex); - - public IEnumerator GetEnumerator() => new Enumerator(array); - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(array); - - class Enumerator : IEnumerator - { - readonly int[] array; - int index = -1; - - public Enumerator(int[] array) => this.array = array; - - public int Current => array[index]; - object IEnumerator.Current => array[index]; - - public bool MoveNext() => ++index < array.Length; - - public void Reset() => throw new NotSupportedException(); - - public void Dispose() { } - } - } - -#pragma warning restore HLQ006 // GetEnumerator() or GetAsyncEnumerator() should return a value type. - - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Benchmarks/Utils/TestEnumerable.cs b/NetFabric.Hyperlinq.Benchmarks/Utils/TestEnumerable.cs deleted file mode 100644 index dc894aa5a..000000000 --- a/NetFabric.Hyperlinq.Benchmarks/Utils/TestEnumerable.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq.Benchmarks -{ - public static class TestEnumerable - { - public static Enumerable ValueType(int[] array) - => new Enumerable(array); - - public static IEnumerable ReferenceType(int[] array) - => new ReferenceEnumerable(array); - - public class Enumerable : IEnumerable - { - readonly int[] array; - - public Enumerable(int[] array) - => this.array = array; - - public Enumerator GetEnumerator() - => new Enumerator(array); - IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(array); - IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(array); - - public struct Enumerator : IEnumerator - { - readonly int[] array; - int index; - - public Enumerator(int[] array) - { - this.array = array; - index = -1; - } - - public int Current => array[index]; - object IEnumerator.Current => array[index]; - - public bool MoveNext() => ++index < array.Length; - - public void Reset() => throw new NotSupportedException(); - - public void Dispose() { } - } - } - - class ReferenceEnumerable : IEnumerable - { - readonly int[] array; - - public ReferenceEnumerable(int[] array) - => this.array = array; - - public IEnumerator GetEnumerator() - => new Enumerator(array); - IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(array); - - class Enumerator : IEnumerator - { - readonly int[] array; - int index = -1; - - public Enumerator(int[] array) => this.array = array; - - public int Current => array[index]; - object IEnumerator.Current => array[index]; - - public bool MoveNext() => ++index < array.Length; - - public void Reset() => throw new NotSupportedException(); - - public void Dispose() { } - } - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Benchmarks/Utils/TestList.cs b/NetFabric.Hyperlinq.Benchmarks/Utils/TestList.cs deleted file mode 100644 index fefd2efa1..000000000 --- a/NetFabric.Hyperlinq.Benchmarks/Utils/TestList.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq.Benchmarks -{ - public static class TestList - { - public static Enumerable ValueType(int[] array) - => new Enumerable(array); - - public static IReadOnlyList ReferenceType(int[] array) - => new EnumerableReferenceType(array); - - public class Enumerable : IReadOnlyList, IList - { - readonly int[] array; - - public Enumerable(int[] array) - => this.array = array; - - public int Count => array.Length; - - public int this[int index] => array[index]; - - int IList.this[int index] - { - get => array[index]; - set => throw new NotImplementedException(); - } - - public bool IsReadOnly => true; - - public void Add(int item) => throw new NotImplementedException(); - public bool Remove(int item) => throw new NotImplementedException(); - public void Clear() => throw new NotImplementedException(); - public int IndexOf(int item) => throw new NotImplementedException(); - public void Insert(int index, int item) => throw new NotImplementedException(); - public void RemoveAt(int index) => throw new NotImplementedException(); - - public bool Contains(int item) - => ((IList)array).Contains(item); - - public void CopyTo(int[] array, int arrayIndex) - => this.array.CopyTo(array, arrayIndex); - - public Enumerator GetEnumerator() - => new Enumerator(array); - IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(array); - IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(array); - - public struct Enumerator : IEnumerator - { - readonly int[] array; - int index; - - public Enumerator(int[] array) - { - this.array = array; - index = -1; - } - - public int Current => array[index]; - object IEnumerator.Current => array[index]; - - public bool MoveNext() => ++index < array.Length; - - public void Reset() => throw new NotSupportedException(); - - public void Dispose() { } - } - } - -#pragma warning disable HLQ006 // GetEnumerator() or GetAsyncEnumerator() should return a value type. - - class EnumerableReferenceType : IReadOnlyList, IList - { - readonly int[] array; - - public EnumerableReferenceType(int[] array) - => this.array = array; - - public int Count => array.Length; - - public int this[int index] => array[index]; - - int IList.this[int index] - { - get => array[index]; - set => throw new NotImplementedException(); - } - - public bool IsReadOnly => true; - - public void Add(int item) => throw new NotImplementedException(); - public bool Remove(int item) => throw new NotImplementedException(); - public void Clear() => throw new NotImplementedException(); - public int IndexOf(int item) => throw new NotImplementedException(); - public void Insert(int index, int item) => throw new NotImplementedException(); - public void RemoveAt(int index) => throw new NotImplementedException(); - - public bool Contains(int item) - => ((IList)array).Contains(item); - - public void CopyTo(int[] array, int arrayIndex) - => this.array.CopyTo(array, arrayIndex); - - public IEnumerator GetEnumerator() => new Enumerator(array); - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(array); - - class Enumerator : IEnumerator - { - readonly int[] array; - int index = -1; - - public Enumerator(int[] array) => this.array = array; - - public int Current => array[index]; - object IEnumerator.Current => array[index]; - - public bool MoveNext() => ++index < array.Length; - - public void Reset() => throw new NotSupportedException(); - - public void Dispose() { } - } - } - -#pragma warning restore HLQ006 // GetEnumerator() or GetAsyncEnumerator() should return a value type. - - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Benchmarks/Utils/Utils.cs b/NetFabric.Hyperlinq.Benchmarks/Utils/Utils.cs index 30f621e72..b63b3d509 100644 --- a/NetFabric.Hyperlinq.Benchmarks/Utils/Utils.cs +++ b/NetFabric.Hyperlinq.Benchmarks/Utils/Utils.cs @@ -1,11 +1,14 @@ using System; +using System.Diagnostics.CodeAnalysis; namespace NetFabric.Hyperlinq.Benchmarks { static class Utils { + [return: NotNull] public static int[] GetSequentialValues(int count) { + // ReSharper disable once HeapView.ObjectAllocation.Evident var array = new int[count]; for (var index = 0; index < count; index++) @@ -14,10 +17,13 @@ public static int[] GetSequentialValues(int count) return array; } + [return: NotNull] public static int[] GetRandomValues(int seed, int count) { + // ReSharper disable once HeapView.ObjectAllocation.Evident var array = new int[count]; + // ReSharper disable once HeapView.ObjectAllocation.Evident var random = new Random(seed); for (var index = 0; index < count; index++) array[index] = random.Next(count); diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.Memory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/Count.ReadOnlySpan.Tests.cs similarity index 75% rename from NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.Memory.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/Count.ReadOnlySpan.Tests.cs index c98625c28..6d121cf48 100644 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.Memory.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/Count.ReadOnlySpan.Tests.cs @@ -5,7 +5,7 @@ namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Count { - public class MemoryTests + public class ReadOnlySpanTests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -14,11 +14,12 @@ public class MemoryTests public void Count_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .Count(source); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Count(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Count(); // Assert @@ -33,11 +34,13 @@ public void Count_With_ValidData_Must_Succeed(int[] source) public void Count_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Count(source, predicate); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) + .Count(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Count(); @@ -53,12 +56,13 @@ public void Count_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .Count(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Count(); diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/Count.ValueEnumerable.Tests.cs similarity index 81% rename from NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/Count.ValueEnumerable.Tests.cs index f2af69211..7c097e6ed 100644 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/Count.ValueEnumerable.Tests.cs @@ -16,12 +16,12 @@ public void Count_With_ValidData_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Count(source); + var expected = source + .Count(); // Act - var result = ValueEnumerableExtensions - .Count, Wrap.Enumerator, int>(wrapped); + var result = wrapped + .Count, Wrap.Enumerator, int>(); // Assert _ = result.Must() @@ -37,12 +37,12 @@ public void Count_Predicate_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Count(); // Assert @@ -59,13 +59,13 @@ public void Count_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Count(); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/Count.ValueReadOnlyCollection.Tests.cs similarity index 76% rename from NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ValueReadOnlyCollection.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/Count.ValueReadOnlyCollection.Tests.cs index a603b9077..f5ce2250f 100644 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/Count.ValueReadOnlyCollection.Tests.cs @@ -16,12 +16,12 @@ public void Count_With_ValidData_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .Count(source); + var expected = source + .Count(); // Act - var result = ValueReadOnlyCollectionExtensions - .Count, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .Count(); // Assert _ = result.Must() diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/CountAsync.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/CountAsync.AsyncValueEnumerable.Tests.cs similarity index 60% rename from NetFabric.Hyperlinq.UnitTests/Aggregation/Count/CountAsync.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/CountAsync.AsyncValueEnumerable.Tests.cs index ab051f465..b0df41458 100644 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/CountAsync.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Count/CountAsync.AsyncValueEnumerable.Tests.cs @@ -12,17 +12,18 @@ public class AsyncValueEnumerableTests [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask CountAsync_With_ValidData_Must_Succeed(int[] source) + public async Task CountAsync_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Count(source); + var expected = source + .Count(); // Act - var result = await AsyncValueEnumerableExtensions - .CountAsync, Wrap.AsyncEnumerator, int>(wrapped); + var result = await wrapped.AsAsyncValueEnumerable() + .CountAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -33,18 +34,19 @@ public async ValueTask CountAsync_With_ValidData_Must_Succeed(int[] source) [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public async ValueTask CountAsync_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task CountAsync_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Count(source, predicate); + var expected = source + .Count(predicate); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .CountAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .CountAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -55,18 +57,20 @@ public async ValueTask CountAsync_Predicate_With_ValidData_Must_Succeed(int[] so [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public async ValueTask CountAsync_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task CountAsync_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable.Where(source, predicate) + var expected = source + .Where(predicate) .Count(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .CountAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .CountAsync() + .ConfigureAwait(false); // Assert _ = result.Must() diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum.TestData.cs b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum.TestData.cs new file mode 100644 index 000000000..a749e624d --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum.TestData.cs @@ -0,0 +1,86 @@ +using System; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + public static TheoryData SumDouble + => new() + { + new double[] { }, + new[] { double.NaN }, + new[] { double.PositiveInfinity }, + new[] { 1.0 }, + new[] { 1.0, 2.0 }, + new[] { 1.0, 2.0, 3.0 }, + new[] { 1.0, 2.0, 3.0, 4.0 }, + new[] { 1.0, 2.0, 3.0, 4.0, 5.0 }, + new[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 }, + new[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 }, + new[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 }, + new[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 }, + new[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0 }, + new[] { double.NaN, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0 }, + new[] { double.PositiveInfinity, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0 }, + new[] { double.MaxValue, double.MaxValue }, + new[] { double.PositiveInfinity, double.PositiveInfinity } + }; + + public static TheoryData SumNullableDouble + => new() + { + new double?[] { }, + new double?[] { default }, + new double?[] { double.NaN }, + new double?[] { double.PositiveInfinity }, + new double?[] { 1.0 }, + new double?[] { 1.0, 2.0 }, + new double?[] { 1.0, 2.0, 3.0 }, + new double?[] { 1.0, 2.0, 3.0, 4.0 }, + new double?[] { 1.0, 2.0, 3.0, 4.0, 5.0 }, + new double?[] { default, default, default }, + new double?[] { default, 2.0, double.NaN, 4.0, default }, + new double?[] { default, 2.0, 3.0, 4.0, default }, + new double?[] { 1.0, 2.0, default, 4.0, 5.0 }, + new double?[] { double.MaxValue, double.MaxValue }, + new double?[] { double.PositiveInfinity, double.PositiveInfinity } + }; + + public static TheoryData SumDecimal + => new() + { + new decimal[] { }, + new[] { 1.0M }, + new[] { 1.0M, 2.0M }, + new[] { 1.0M, 2.0M, 3.0M }, + new[] { 1.0M, 2.0M, 3.0M, 4.0M }, + new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M }, + new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M }, + new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M, 7.0M }, + new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M, 7.0M, 8.0M }, + new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M, 7.0M, 8.0M, 9.0M }, + new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M, 7.0M, 8.0M, 9.0M, 10.0M, 11.0M, 12.0M, 13.0M, 14.0M, 15.0M, 16.0M, 17.0M, 18.0M, 19.0M, 20.0M }, + //new[] { decimal.MaxValue, decimal.MaxValue }, + }; + + + public static TheoryData SumNullableDecimal + => new() + { + new decimal?[] { }, + new decimal?[] { default }, + new decimal?[] { 1.0M }, + new decimal?[] { 1.0M, 2.0M }, + new decimal?[] { 1.0M, 2.0M, 3.0M }, + new decimal?[] { 1.0M, 2.0M, 3.0M, 4.0M }, + new decimal?[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M }, + new decimal?[] { default, default, default }, + new decimal?[] { default, 2.0M, 3.0M, 4.0M, default }, + new decimal?[] { 1.0M, 2.0M, default, 4.0M, 5.0M }, + //new decimal?[] { decimal.MaxValue, decimal.MaxValue }, + }; + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/Sum.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/Sum.ReadOnlySpan.Tests.cs new file mode 100644 index 000000000..0515270bd --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/Sum.ReadOnlySpan.Tests.cs @@ -0,0 +1,84 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum +{ + public class ArrayTests + { + + [Theory] + [MemberData(nameof(TestData.SumDouble), MemberType = typeof(TestData))] + public void Sum_With_Double_Must_Succeed(double[] source) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SumNullableDouble), MemberType = typeof(TestData))] + public void Sum_With_NullableDouble_Must_Succeed(double?[] source) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected!.Value); + } + + + [Theory] + [MemberData(nameof(TestData.SumDecimal), MemberType = typeof(TestData))] + public void Sum_With_Decimal_Must_Succeed(decimal[] source) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SumNullableDecimal), MemberType = typeof(TestData))] + public void Sum_With_NullableDecimal_ValidData_Must_Succeed(decimal?[] source) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected!.Value); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/Sum.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/Sum.ValueEnumerable.Tests.cs new file mode 100644 index 000000000..2f8bdac05 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/Sum.ValueEnumerable.Tests.cs @@ -0,0 +1,82 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum +{ + public class ValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.SumDouble), MemberType = typeof(TestData))] + public void Sum_With_Double_Must_Succeed(double[] source) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SumNullableDouble), MemberType = typeof(TestData))] + public void Sum_With_NullableDouble_Must_Succeed(double?[] source) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected!.Value); + } + + [Theory] + [MemberData(nameof(TestData.SumDecimal), MemberType = typeof(TestData))] + public void Sum_With_Decimal_Must_Succeed(decimal[] source) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SumNullableDecimal), MemberType = typeof(TestData))] + public void Sum_With_NullableDecimal_Must_Succeed(decimal?[] source) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected!.Value); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/Sum.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/Sum.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..d1078b274 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/Sum.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,82 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum +{ + public class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.SumDouble), MemberType = typeof(TestData))] + public void Sum_With_Double_Must_Succeed(double[] source) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SumNullableDouble), MemberType = typeof(TestData))] + public void Sum_With_NullableDouble_Must_Succeed(double?[] source) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected!.Value); + } + + [Theory] + [MemberData(nameof(TestData.SumDecimal), MemberType = typeof(TestData))] + public void Sum_With_Decimal_Must_Succeed(decimal[] source) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SumNullableDecimal), MemberType = typeof(TestData))] + public void Sum_With_NullableDecimal_Must_Succeed(decimal?[] source) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected!.Value); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/SumAsync.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/SumAsync.AsyncValueEnumerable.Tests.cs new file mode 100644 index 000000000..b6ca37841 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Aggregation/Sum/SumAsync.AsyncValueEnumerable.Tests.cs @@ -0,0 +1,87 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum +{ + public class AsyncValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.SumDouble), MemberType = typeof(TestData))] + public async Task SumAsync_With_Double_Must_Succeed(double[] source) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = await wrapped.AsAsyncValueEnumerable() + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SumNullableDouble), MemberType = typeof(TestData))] + public async Task SumAsync_With_NullableDouble_Must_Succeed(double?[] source) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = await wrapped.AsAsyncValueEnumerable() + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected!.Value); + } + + [Theory] + [MemberData(nameof(TestData.SumDecimal), MemberType = typeof(TestData))] + public async Task SumAsync_With_Decimal_Must_Succeed(decimal[] source) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = await wrapped.AsAsyncValueEnumerable() + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SumNullableDecimal), MemberType = typeof(TestData))] + public async Task SumAsync_With_NullableDecimal_Must_Succeed(decimal?[] source) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = await wrapped.AsAsyncValueEnumerable() + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected!.Value); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.Tests.cs similarity index 92% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.Tests.cs index 97bd55296..5e4f493ea 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.Tests.cs @@ -1,4 +1,5 @@ using NetFabric.Assertive; +using System; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsAsyncEnumerable @@ -9,7 +10,7 @@ public class AsyncValueEnumerableTests public void AsAsyncEnumerable_With_ValueType_Must_ReturnCopy() { // Arrange - var source = new int[0]; + var source = Array.Empty(); var wrapped = Wrap.AsAsyncValueEnumerable(source); // Act @@ -25,7 +26,7 @@ public void AsAsyncEnumerable_With_ValueType_Must_ReturnCopy() public void AsAsyncEnumerable_With_ReferenceType_Must_ReturnSame() { // Arrange - var source = new int[0]; + var source = Array.Empty(); var wrapped = Wrap .AsAsyncValueEnumerable(source) as IAsyncValueEnumerable>; diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncEnumerable.Tests.cs new file mode 100644 index 000000000..fa4d93c24 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncEnumerable.Tests.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NetFabric.Assertive; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsAsyncValueEnumerable +{ + public partial class AsyncEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsAsyncValueEnumerable1_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncEnumerable(source); + + // Act + var result = wrapped + .AsAsyncValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, Wrap.AsyncEnumerator, Wrap.AsyncEnumerator, int, Wrap.AsyncEnumerableWrapper.GetAsyncEnumeratorFunction, Wrap.AsyncEnumerableWrapper.GetAsyncEnumeratorFunction>>() + .BeAsyncEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public async Task AsAsyncValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = await wrapped + .AsAsyncValueEnumerable() + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncValueEnumerable.Tests.cs new file mode 100644 index 000000000..13562a3fc --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncValueEnumerable.Tests.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NetFabric.Assertive; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsAsyncValueEnumerable +{ + public partial class AsyncValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsAsyncValueEnumerable1_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncValueEnumerable(source); + + // Act + var result = wrapped + .AsAsyncValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, Wrap.AsyncEnumerator, Wrap.AsyncEnumerator, int, Wrap.AsyncValueEnumerableWrapper.GetAsyncEnumeratorFunction, Wrap.AsyncValueEnumerableWrapper.GetAsyncEnumeratorFunction>>() + .BeAsyncEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public async Task AsAsyncValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = await wrapped + .AsAsyncValueEnumerable() + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncEnumerable.Tests.cs new file mode 100644 index 000000000..69a6bdbef --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncEnumerable.Tests.cs @@ -0,0 +1,82 @@ +using System.Linq; +using NetFabric.Assertive; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsAsyncValueEnumerable +{ + public partial class AsyncEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsAsyncValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncEnumerable(source); + + // Act + var result = wrapped + .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, int>( + (enumerable, _) => enumerable.GetAsyncEnumerator()); + + // Assert + _ = result.Must() + .BeAsyncEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsAsyncValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncEnumerable(source); + + // Act + var result = wrapped + .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, + AsyncValueEnumerator, int>( + (enumerable, _) => enumerable.GetAsyncEnumerator(), + (enumerable, cancellationToken) => + new AsyncValueEnumerator( + ((IAsyncEnumerable)enumerable).GetAsyncEnumerator(cancellationToken))); + + // Assert + _ = result.Must() + .BeAsyncEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public async Task AsAsyncValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = await wrapped + .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, AsyncValueEnumerator, int>( + (enumerable, _) => enumerable.GetAsyncEnumerator(), + (enumerable, cancellationToken) => new AsyncValueEnumerator(((IAsyncEnumerable)enumerable).GetAsyncEnumerator(cancellationToken))) + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncValueEnumerable.Tests.cs new file mode 100644 index 000000000..7d1f42958 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncValueEnumerable.Tests.cs @@ -0,0 +1,84 @@ +using System.Linq; +using NetFabric.Assertive; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsAsyncValueEnumerable +{ + public partial class AsyncValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsAsyncValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncValueEnumerable(source); + + // Act + var result = AsyncValueEnumerableExtensions + .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, int>( + wrapped, + (enumerable, _) => enumerable.GetAsyncEnumerator()); + + // Assert + _ = result.Must() + .BeAsyncEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsAsyncValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncValueEnumerable(source); + + // Act + var result = AsyncValueEnumerableExtensions + .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, AsyncValueEnumerator, int>( + wrapped, + (enumerable, _) => enumerable.GetAsyncEnumerator(), + (enumerable, cancellationToken) => + new AsyncValueEnumerator( + ((IAsyncEnumerable)enumerable).GetAsyncEnumerator(cancellationToken))); + + // Assert + _ = result.Must() + .BeAsyncEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public async Task AsAsyncValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsAsyncValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = await AsyncValueEnumerableExtensions + .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, AsyncValueEnumerator, int>( + wrapped, + (enumerable, _) => enumerable.GetAsyncEnumerator(), + (enumerable, cancellationToken) => new AsyncValueEnumerator(((IAsyncEnumerable)enumerable).GetAsyncEnumerator(cancellationToken))) + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsEnumerable/AsEnumerable.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsEnumerable/AsEnumerable.ValueEnumerable.Tests.cs similarity index 100% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsEnumerable/AsEnumerable.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsEnumerable/AsEnumerable.ValueEnumerable.Tests.cs diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Enumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs similarity index 53% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Enumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs index 50a35132f..3a7e9a632 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Enumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs @@ -1,58 +1,50 @@ -using NetFabric.Assertive; -using System; -using System.Collections.Generic; using System.Linq; +using NetFabric.Assertive; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable { - public class EnumerableTests + public partial class EnumerableTests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToList_With_ValidData_Must_Succeed(int[] source) + public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap .AsEnumerable(source); - var expected = Enumerable - .ToList(source); // Act - var result = EnumerableExtensions - .AsValueEnumerable(wrapped) - .ToList(); + var result = wrapped + .AsValueEnumerable(); // Assert _ = result.Must() - .BeOfType>() .BeEnumerableOf() - .BeEqualTo(expected); + .BeEqualTo(source); } - + [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToList_With_ValidData_Collections_Must_Succeed(int[] source) + public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap - .AsCollection(source); - var expected = Enumerable - .ToList(source); + .AsEnumerable(source); + var expected = source + .Sum(); // Act - var result = EnumerableExtensions - .AsValueEnumerable(wrapped) - .ToList(); + var result = wrapped + .AsValueEnumerable() + .Sum(); // Assert _ = result.Must() - .BeOfType>() - .BeEnumerableOf() .BeEqualTo(expected); } } diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..5550c1295 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs @@ -0,0 +1,73 @@ +using System.Linq; +using NetFabric.Assertive; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + + // Act + var result = wrapped + .AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + var expected = source + .Count(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + var expected = source + .Sum(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.Array.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueEnumerable.Tests.cs similarity index 51% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.Array.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueEnumerable.Tests.cs index 03ea53857..99625d156 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.Array.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueEnumerable.Tests.cs @@ -1,52 +1,51 @@ -using System; -using System.Buffers; using System.Linq; using NetFabric.Assertive; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToArray +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable { - public class ArrayTests + public partial class ValueEnumerableTests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToArray_Must_Succeed(int[] source) + public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .ToArray(source); + var wrapped = Wrap + .AsValueEnumerable(source); // Act - var result = source.AsValueEnumerable() - .ToArray(); + var result = wrapped + .AsValueEnumerable(); // Assert _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); + .BeEnumerableOf() + .BeEqualTo(source); } - + [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToArray_MemoryPool_Must_Succeed(int[] source) + public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) { // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .ToArray(source); + var wrapped = Wrap + .AsValueEnumerable(source); + var expected = source + .Sum(); // Act - using var result = source.AsValueEnumerable() - .ToArray(pool); + var result = wrapped + .AsValueEnumerable() + .Sum(); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEqualTo(expected); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..48ef26ecb --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,73 @@ +using System.Linq; +using NetFabric.Assertive; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueReadOnlyCollection1_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + + // Act + var result = wrapped + .AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueReadOnlyCollection1_Count_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Count(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueReadOnlyCollection1_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Sum(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyList.Tests.cs new file mode 100644 index 000000000..0b443cb83 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyList.Tests.cs @@ -0,0 +1,73 @@ +using System.Linq; +using NetFabric.Assertive; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ValueReadOnlyListTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueReadOnlyList1_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + + // Act + var result = wrapped + .AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueReadOnlyList1_Count_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Count(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueReadOnlyList1_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Sum(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs new file mode 100644 index 000000000..abb36fdea --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs @@ -0,0 +1,77 @@ +using System.Linq; +using NetFabric.Assertive; +using System.Collections.Generic; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class EnumerableTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsEnumerable(source); + + // Act + var result = wrapped + .AsValueEnumerable, Wrap.Enumerator, int>( + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsEnumerable(source); + + // Act + var result = wrapped + .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( + enumerable => enumerable.GetEnumerator(), + enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = wrapped + .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( + enumerable => enumerable.GetEnumerator(), + enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..a7911b8d9 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs @@ -0,0 +1,105 @@ +using System.Linq; +using NetFabric.Assertive; +using System.Collections.Generic; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + + // Act + var result = ReadOnlyCollectionExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + + // Act + var result = ReadOnlyCollectionExtensions + .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator(), + enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Count_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + var expected = source + .Count(); + + // Act + var result = ReadOnlyCollectionExtensions + .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator(), + enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())) + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + var expected = source + .Sum(); + + // Act + var result = ReadOnlyCollectionExtensions + .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator(), + enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs new file mode 100644 index 000000000..5c933ab0c --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs @@ -0,0 +1,78 @@ +using System.Linq; +using NetFabric.Assertive; +using System.Collections.Generic; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueEnumerable(source); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueEnumerable(source); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..36089a9a5 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,101 @@ +using System.Linq; +using NetFabric.Assertive; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Count_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Count(); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()) + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Sum(); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyList.Tests.cs new file mode 100644 index 000000000..55b702568 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyList.Tests.cs @@ -0,0 +1,101 @@ +using System.Linq; +using NetFabric.Assertive; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ValueReadOnlyListTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Count_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Count(); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()) + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Sum(); + + // Act + var result = ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs new file mode 100644 index 000000000..f074dee01 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs @@ -0,0 +1,124 @@ +using System.Linq; +using NetFabric.Assertive; +using System; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ArraySegmentTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = new ArraySegment(source); + + // Act + var result = wrapped + .AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source, testRefStructs: false); + result.SequenceEqual(source).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = new ArraySegment(source); + var expected = source + .Skip(count0) + .Skip(count1); + + // Act + var result = wrapped + .AsValueEnumerable() + .Skip(count0) + .Skip(count1); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = new ArraySegment(source); + var expected = source + .Take(count0) + .Take(count1); + + // Act + var result = wrapped + .AsValueEnumerable() + .Take(count0) + .Take(count1); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) + { + // Arrange + var wrapped = new ArraySegment(source); + var expected = source + .Skip(skipCount) + .Take(takeCount) + .Count(); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(skipCount) + .Take(takeCount) + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) + { + // Arrange + var wrapped = new ArraySegment(source); + var expected = source + .Skip(skipCount) + .Take(takeCount) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(skipCount) + .Take(takeCount) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs new file mode 100644 index 000000000..839b6bc1d --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs @@ -0,0 +1,126 @@ +using System.Linq; +using NetFabric.Assertive; +using System; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ReadOnlyMemoryTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + + // Act + var result = wrapped + .AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source, testRefStructs: false); + result.SequenceEqual(source).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Skip(count0) + .Skip(count1); + + // Act + var result = wrapped + .AsValueEnumerable() + .Skip(count0) + .Skip(count1); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Take(count0) + .Take(count1); + + // Act + var result = wrapped + .AsValueEnumerable() + .Take(count0) + .Take(count1); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Skip(skipCount) + .Take(takeCount) + .Count(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Skip(skipCount) + .Take(takeCount) + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Skip(skipCount) + .Take(takeCount) + .Sum(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Skip(skipCount) + .Take(takeCount) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.Tests.cs new file mode 100644 index 000000000..112315775 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.Tests.cs @@ -0,0 +1,117 @@ +using System.Linq; +using NetFabric.Assertive; +using System; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +{ + public partial class ReadOnlySpanTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + + // Act + var result = wrapped + .AsValueEnumerable(); + + // Assert + result.SequenceEqual(source).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Skip(count0) + .Skip(count1); + + // Act + var result = wrapped + .AsValueEnumerable() + .Skip(count0) + .Skip(count1); + + // Assert + result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Take(count0) + .Take(count1); + + // Act + var result = wrapped + .AsValueEnumerable() + .Take(count0) + .Take(count1); + + // Assert + result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Skip(skipCount) + .Take(takeCount) + .Count(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Skip(skipCount) + .Take(takeCount) + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Skip(skipCount) + .Take(takeCount) + .Sum(); + + // Act + var result = wrapped + .AsValueEnumerable() + .Skip(skipCount) + .Take(takeCount) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/Dictionary.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/Dictionary.Tests.cs new file mode 100644 index 000000000..da7634e75 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/Dictionary.Tests.cs @@ -0,0 +1,67 @@ +using NetFabric.Assertive; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Generic +{ + public class DictionaryTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_Dictionary_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = source.ToDictionary(item => item); + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, Dictionary.Enumerator, Dictionary.Enumerator, KeyValuePair, DictionaryExtensions.GetEnumerator, DictionaryExtensions.GetEnumerator>>() + .BeEnumerableOf>() + .BeEqualTo(wrapped); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_Dictionary_KeyCollection_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = source.ToDictionary(item => item).Keys; + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType.KeyCollection, Dictionary.KeyCollection.Enumerator, Dictionary.KeyCollection.Enumerator, int, DictionaryExtensions.GetEnumerator, DictionaryExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_Dictionary_ValueCollection_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = source.ToDictionary(item => item).Values; + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType.ValueCollection, Dictionary.ValueCollection.Enumerator, Dictionary.ValueCollection.Enumerator, int, DictionaryExtensions.GetEnumerator, DictionaryExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/HashSet.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/HashSet.Tests.cs new file mode 100644 index 000000000..4c9380d26 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/HashSet.Tests.cs @@ -0,0 +1,28 @@ +using NetFabric.Assertive; +using System.Collections.Generic; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Generic +{ + public class HashSetTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_HashSet_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = new HashSet(source); + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, HashSet.Enumerator, HashSet.Enumerator, int, HashSetExtensions.GetEnumerator, HashSetExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/LinkedList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/LinkedList.Tests.cs new file mode 100644 index 000000000..8c64acfcd --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/LinkedList.Tests.cs @@ -0,0 +1,28 @@ +using NetFabric.Assertive; +using System.Collections.Generic; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Generic +{ + public class LinkedListTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_LinkedList_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = new LinkedList(source); + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, LinkedList.Enumerator, LinkedList.Enumerator, int, LinkedListExtensions.GetEnumerator, LinkedListExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs similarity index 88% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs index fa8c023a4..09510ab21 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs @@ -24,8 +24,8 @@ public void AsValueEnumerable_With_List_Must_ReturnWrapper(int[] source) _ = result.Must() .BeOfType>() .BeEnumerableOf() - .BeEqualTo(source, testRefStructs: false); - _ = result.SequenceEqual(source).Must().BeTrue(); + .BeEqualTo(wrapped, testRefStructs: false); + _ = result.SequenceEqual(wrapped).Must().BeTrue(); } } } diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/PriorityQueue.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/PriorityQueue.Tests.cs new file mode 100644 index 000000000..a26e370ad --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/PriorityQueue.Tests.cs @@ -0,0 +1,33 @@ +#if NET60_OR_GREATER + +using NetFabric.Assertive; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Generic +{ + public class PriorityQueueTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_PriorityQueue_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = new PriorityQueue(source.Select(item => (item, 0))); + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, PriorityQueue.Enumerator, PriorityQueue.Enumerator, int, PriorityQueueExtensions.GetEnumerator, PriorityQueueExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + } +} + +#endif diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/Queue.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/Queue.Tests.cs new file mode 100644 index 000000000..b8632d9b1 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/Queue.Tests.cs @@ -0,0 +1,28 @@ +using NetFabric.Assertive; +using System.Collections.Generic; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Generic +{ + public class QueueTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_Queue_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = new Queue(source); + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, Queue.Enumerator, Queue.Enumerator, int, QueueExtensions.GetEnumerator, QueueExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/SortedDictionary.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/SortedDictionary.Tests.cs new file mode 100644 index 000000000..d035b2de2 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/SortedDictionary.Tests.cs @@ -0,0 +1,67 @@ +using NetFabric.Assertive; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Generic +{ + public class SortedDictionaryTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_SortedDictionary_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = new SortedDictionary(source.ToDictionary(item => item)); + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, SortedDictionary.Enumerator, SortedDictionary.Enumerator, KeyValuePair, SortedDictionaryExtensions.GetEnumerator, SortedDictionaryExtensions.GetEnumerator>>() + .BeEnumerableOf>() + .BeEqualTo(wrapped); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_SortedDictionary_KeyCollection_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = new SortedDictionary(source.ToDictionary(item => item)).Keys; + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType.KeyCollection, SortedDictionary.KeyCollection.Enumerator, SortedDictionary.KeyCollection.Enumerator, int, SortedDictionaryExtensions.GetEnumerator, SortedDictionaryExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_SortedDictionary_ValueCollection_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = new SortedDictionary(source.ToDictionary(item => item)).Values; + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType.ValueCollection, SortedDictionary.ValueCollection.Enumerator, SortedDictionary.ValueCollection.Enumerator, int, SortedDictionaryExtensions.GetEnumerator, SortedDictionaryExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/SortedSet.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/SortedSet.Tests.cs new file mode 100644 index 000000000..de3cd6fa6 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/SortedSet.Tests.cs @@ -0,0 +1,28 @@ +using NetFabric.Assertive; +using System.Collections.Generic; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Generic +{ + public class SortedSetTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_SortedSet_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = new SortedSet(source); + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, SortedSet.Enumerator, SortedSet.Enumerator, int, SortedSetExtensions.GetEnumerator, SortedSetExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/Stack.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/Stack.Tests.cs new file mode 100644 index 000000000..3483133e8 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/Stack.Tests.cs @@ -0,0 +1,28 @@ +using NetFabric.Assertive; +using System.Collections.Generic; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Generic +{ + public class StackTests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable_With_Stack_Must_ReturnWrapper(int[] source) + { + // Arrange + var wrapped = new Stack(source); + + // Act + var result = wrapped.AsValueEnumerable(); + + // Assert + _ = result.Must() + .BeOfType, Stack.Enumerator, Stack.Enumerator, int, StackExtensions.GetEnumerator, StackExtensions.GetEnumerator>>() + .BeEnumerableOf() + .BeEqualTo(wrapped); + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs similarity index 70% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs index b46dd59c4..3d0d57576 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs @@ -1,5 +1,6 @@ using NetFabric.Assertive; using System.Collections.Immutable; +using System.Linq; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Immutable @@ -20,10 +21,10 @@ public void AsValueEnumerable_With_ImmutableArray_Must_ReturnWrapper(int[] sourc // Assert _ = result.Must() - .BeOfType>() -// .BeOfType, ValueEnumerator, ImmutableArray.Enumerator, int, ImmutableArrayExtensions.GetEnumerator, ImmutableArrayExtensions.GetEnumerator2>>() + .BeOfType>() .BeEnumerableOf() - .BeEqualTo(source); + .BeEqualTo(wrapped, testRefStructs: false); + _ = result.SequenceEqual(wrapped).Must().BeTrue(); } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableDictionary.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableDictionary.Tests.cs similarity index 92% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableDictionary.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableDictionary.Tests.cs index 873100528..44afc4031 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableDictionary.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableDictionary.Tests.cs @@ -16,7 +16,6 @@ public void AsValueEnumerable_With_ImmutableDictionary_Must_ReturnWrapper(int[] { // Arrange var wrapped = source.ToImmutableDictionary(item => item, default); - var expected = source.ToDictionary(item => item); // Act var result = wrapped.AsValueEnumerable(); @@ -25,7 +24,7 @@ public void AsValueEnumerable_With_ImmutableDictionary_Must_ReturnWrapper(int[] _ = result.Must() .BeOfType, ImmutableDictionary.Enumerator, ImmutableDictionary.Enumerator, KeyValuePair, ImmutableDictionaryExtensions.GetEnumerator, ImmutableDictionaryExtensions.GetEnumerator>>() .BeEnumerableOf>() - .BeEqualTo(expected); + .BeEqualTo(wrapped); } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableHashSet.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableHashSet.Tests.cs similarity index 96% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableHashSet.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableHashSet.Tests.cs index b09af691f..8b8c86381 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableHashSet.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableHashSet.Tests.cs @@ -22,7 +22,7 @@ public void AsValueEnumerable_With_ImmutableHashSet_Must_ReturnWrapper(int[] sou _ = result.Must() .BeOfType, ImmutableHashSet.Enumerator, ImmutableHashSet.Enumerator, int, ImmutableHashSetExtensions.GetEnumerator, ImmutableHashSetExtensions.GetEnumerator>>() .BeEnumerableOf() - .BeEqualTo(source); + .BeEqualTo(wrapped); } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableList.Tests.cs similarity index 96% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableList.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableList.Tests.cs index 52f311575..159ca6cbb 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableList.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableList.Tests.cs @@ -22,7 +22,7 @@ public void AsValueEnumerable_With_ImmutableList_Must_ReturnWrapper(int[] source _ = result.Must() .BeOfType, ImmutableList.Enumerator, ImmutableList.Enumerator, int, ImmutableListExtensions.GetEnumerator, ImmutableListExtensions.GetEnumerator>>() .BeEnumerableOf() - .BeEqualTo(source); + .BeEqualTo(wrapped); } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableQueue.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableQueue.Tests.cs similarity index 96% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableQueue.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableQueue.Tests.cs index cb5170afe..9537f752c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableQueue.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableQueue.Tests.cs @@ -22,7 +22,7 @@ public void AsValueEnumerable_With_ImmutableQueue_Must_ReturnWrapper(int[] sourc _ = result.Must() .BeOfType, ValueEnumerator, ImmutableQueue.Enumerator, int, ImmutableQueueExtensions.GetEnumerator, ImmutableQueueExtensions.GetEnumerator2>>() .BeEnumerableOf() - .BeEqualTo(source); + .BeEqualTo(wrapped); } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableSortedDictionary.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableSortedDictionary.Tests.cs similarity index 92% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableSortedDictionary.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableSortedDictionary.Tests.cs index b6fb4c7da..167ad7adc 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableSortedDictionary.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableSortedDictionary.Tests.cs @@ -17,7 +17,6 @@ public void AsValueEnumerable_With_ImmutableSortedDictionry_Must_ReturnWrapper(i // Arrange var dictionary = source.ToDictionary(item => item); var wrapped = ImmutableSortedDictionary.CreateRange(default, dictionary); - var expected = new SortedDictionary(dictionary); // Act var result = wrapped.AsValueEnumerable(); @@ -26,7 +25,7 @@ public void AsValueEnumerable_With_ImmutableSortedDictionry_Must_ReturnWrapper(i _ = result.Must() .BeOfType, ImmutableSortedDictionary.Enumerator, ImmutableSortedDictionary.Enumerator, KeyValuePair, ImmutableSortedDictionaryExtensions.GetEnumerator, ImmutableSortedDictionaryExtensions.GetEnumerator>>() .BeEnumerableOf>() - .BeEqualTo(expected); + .BeEqualTo(wrapped); } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableStack.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableStack.Tests.cs similarity index 92% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableStack.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableStack.Tests.cs index c4968d930..6c3f96577 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableStack.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableStack.Tests.cs @@ -15,7 +15,6 @@ public void AsValueEnumerable_With_ImmutableStack_Must_ReturnWrapper(int[] sourc { // Arrange var wrapped = ImmutableStack.Create(source); - var expected = new Stack(source); // Act var result = wrapped.AsValueEnumerable(); @@ -24,7 +23,7 @@ public void AsValueEnumerable_With_ImmutableStack_Must_ReturnWrapper(int[] sourc _ = result.Must() .BeOfType, ValueEnumerator, ImmutableStack.Enumerator, int, ImmutableStackExtensions.GetEnumerator, ImmutableStackExtensions.GetEnumerator2>>() .BeEnumerableOf() - .BeEqualTo(expected); + .BeEqualTo(wrapped); } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ArrayBuilder.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ArrayBuilder.Tests.cs similarity index 100% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ArrayBuilder.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ArrayBuilder.Tests.cs diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/LargeArrayBuilder.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/LargeArrayBuilder.Tests.cs similarity index 79% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/LargeArrayBuilder.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/LargeArrayBuilder.Tests.cs index 8897c7f7a..2fec2ac88 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/LargeArrayBuilder.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/LargeArrayBuilder.Tests.cs @@ -20,7 +20,7 @@ public void ToArray_Must_Succeed(int count) var expected = Enumerable .Range(0, count) .ToArray(); - using var builder = new LargeArrayBuilder(ArrayPool.Shared); + using var builder = new LargeArrayBuilder(ArrayPool.Shared, false); for (var index = 0; index < count; index++) builder.Add(expected[index]); @@ -39,19 +39,21 @@ public void ToArray_Must_Succeed(int count) public void ToArray_MemoryPool_Must_Succeed(int count) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var expected = Enumerable .Range(0, count) .ToArray(); - using var builder = new LargeArrayBuilder(ArrayPool.Shared); + // ReSharper disable once ConvertToUsingDeclaration + using var builder = new LargeArrayBuilder(pool, false); for (var index = 0; index < count; index++) builder.Add(expected[index]); // Act - using var result = builder.ToArray(pool); + using var result = builder.ToArray(pool, false); // Assert - _ = result.Memory.Must() + _ = result.Must() + .BeEnumerableOf() .BeEqualTo(expected); } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs similarity index 84% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs index 0f754527c..7b7e23ae0 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs @@ -17,8 +17,8 @@ public void ToArray_Must_Succeed(int[] source, int skip, int take) { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .ToArray(); @@ -30,9 +30,10 @@ public void ToArray_Must_Succeed(int[] source, int skip, int take) // Assert _ = result.Must() - .BeNotSameAs(source) .BeArrayOf() .BeEqualTo(expected); + if (result.Length is not 0) + _ = result.Must().BeNotSameAs(source); } [Theory] @@ -42,22 +43,24 @@ public void ToArray_Must_Succeed(int[] source, int skip, int take) public void ToArray_MemoryPool_Must_Succeed(int[] source, int skip, int take) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .ToArray(); // Act + // ReSharper disable once ConvertToUsingDeclaration using var result = wrapped.AsValueEnumerable() .Skip(skip) .Take(take) .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -71,8 +74,8 @@ public void ToArray_Predicate_Must_Succeed(int[] source, int skip, int take, Fun { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Where(predicate) .ToArray(); @@ -86,9 +89,10 @@ public void ToArray_Predicate_Must_Succeed(int[] source, int skip, int take, Fun // Assert _ = result.Must() - .BeNotSameAs(source) .BeArrayOf() .BeEqualTo(expected); + if (result.Length is not 0) + _ = result.Must().BeNotSameAs(source); } [Theory] @@ -98,10 +102,10 @@ public void ToArray_Predicate_Must_Succeed(int[] source, int skip, int take, Fun public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func predicate) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Where(predicate) .ToArray(); @@ -114,8 +118,9 @@ public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, int skip, in .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -129,8 +134,8 @@ public void ToArray_PredicateAt_Must_Succeed(int[] source, int skip, int take, F { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Where(predicate) .ToArray(); @@ -144,9 +149,10 @@ public void ToArray_PredicateAt_Must_Succeed(int[] source, int skip, int take, F // Assert _ = result.Must() - .BeNotSameAs(source) .BeArrayOf() .BeEqualTo(expected); + if (result.Length is not 0) + _ = result.Must().BeNotSameAs(source); } [Theory] @@ -156,10 +162,10 @@ public void ToArray_PredicateAt_Must_Succeed(int[] source, int skip, int take, F public void ToArray_PredicateAt_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func predicate) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Where(predicate) .ToArray(); @@ -172,8 +178,9 @@ public void ToArray_PredicateAt_MemoryPool_Must_Succeed(int[] source, int skip, .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -187,8 +194,8 @@ public void ToArray_Selector_Must_Succeed(int[] source, int skip, int take, Func { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Select(selector) .ToArray(); @@ -214,10 +221,10 @@ public void ToArray_Selector_Must_Succeed(int[] source, int skip, int take, Func public void ToArray_Selector_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Select(selector) .ToArray(); @@ -230,8 +237,9 @@ public void ToArray_Selector_MemoryPool_Must_Succeed(int[] source, int skip, int .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -245,8 +253,8 @@ public void ToArray_SelectorAt_Must_Succeed(int[] source, int skip, int take, Fu { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Select(selector) .ToArray(); @@ -272,10 +280,10 @@ public void ToArray_SelectorAt_Must_Succeed(int[] source, int skip, int take, Fu public void ToArray_SelectorAt_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Select(selector) .ToArray(); @@ -288,8 +296,9 @@ public void ToArray_SelectorAt_MemoryPool_Must_Succeed(int[] source, int skip, i .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -303,8 +312,8 @@ public void ToArray_Predicate_Selector_Must_Succeed(int[] source, int skip, int { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Where(predicate) .Select(selector) @@ -332,10 +341,10 @@ public void ToArray_Predicate_Selector_Must_Succeed(int[] source, int skip, int public void ToArray_Predicate_Selector_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func predicate, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Where(predicate) .Select(selector) @@ -350,8 +359,9 @@ public void ToArray_Predicate_Selector_MemoryPool_Must_Succeed(int[] source, int .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.Memory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ReadOnlySpan.Tests.cs similarity index 72% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.Memory.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ReadOnlySpan.Tests.cs index c4388323f..875c29bcd 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.Memory.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ReadOnlySpan.Tests.cs @@ -6,7 +6,7 @@ namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToArray { - public class MemoryTests + public class ReadOnlySpanTests { [Theory] @@ -16,16 +16,18 @@ public class MemoryTests public void ToArray_MemoryPool_Must_Succeed(int[] source) { // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .ToArray(source); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var pool = ArrayPool.Shared; + var expected = source + .ToArray(); // Act - using var result = source.AsMemory().AsValueEnumerable() + using var result = wrapped.AsValueEnumerable() .ToArray(pool); // Assert - _ = result.Memory.Must() + _ = result.Must() + .BeEnumerableOf() .BeEqualTo(expected); } @@ -39,20 +41,22 @@ public void ToArray_MemoryPool_Must_Succeed(int[] source) public void ToArray_Predicate_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .ToArray(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .ToArray(); // Assert _ = result.Must() - .BeNotSameAs(source) .BeArrayOf() .BeEqualTo(expected); + if (result.Length is not 0) + _ = result.Must().BeNotSameAs(source); } [Theory] @@ -62,18 +66,20 @@ public void ToArray_Predicate_Must_Succeed(int[] source, Func predica public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, Func predicate) { // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var pool = ArrayPool.Shared; + var expected = source + .Where(predicate) .ToArray(); // Act - using var result = source.AsMemory().AsValueEnumerable() + using var result = wrapped.AsValueEnumerable() .Where(predicate) .ToArray(pool); // Assert - _ = result.Memory.Must() + _ = result.Must() + .BeEnumerableOf() .BeEqualTo(expected); } @@ -87,20 +93,22 @@ public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .ToArray(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .ToArray(); // Assert _ = result.Must() - .BeNotSameAs(source) .BeArrayOf() .BeEqualTo(expected); + if (result.Length is not 0) + _ = result.Must().BeNotSameAs(source); } [Theory] @@ -110,18 +118,20 @@ public void ToArray_PredicateAt_Must_Succeed(int[] source, Func public void ToArray_PredicateAt_MemoryPool_Must_Succeed(int[] source, Func predicate) { // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var pool = ArrayPool.Shared; + var expected = source + .Where(predicate) .ToArray(); // Act - using var result = source.AsMemory().AsValueEnumerable() + using var result = wrapped.AsValueEnumerable() .Where(predicate) .ToArray(pool); // Assert - _ = result.Memory.Must() + _ = result.Must() + .BeEnumerableOf() .BeEqualTo(expected); } @@ -135,12 +145,13 @@ public void ToArray_PredicateAt_MemoryPool_Must_Succeed(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .ToArray(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .ToArray(); @@ -158,18 +169,20 @@ public void ToArray_Selector_Must_Succeed(int[] source, Func select public void ToArray_Selector_MemoryPool_Must_Succeed(int[] source, Func selector) { // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var pool = ArrayPool.Shared; + var expected = source + .Select(selector) .ToArray(); // Act - using var result = source.AsMemory().AsValueEnumerable() + using var result = wrapped.AsValueEnumerable() .Select(selector) .ToArray(pool); // Assert - _ = result.Memory.Must() + _ = result.Must() + .BeEnumerableOf() .BeEqualTo(expected); } @@ -183,12 +196,13 @@ public void ToArray_Selector_MemoryPool_Must_Succeed(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .ToArray(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .ToArray(); @@ -206,18 +220,20 @@ public void ToArray_SelectorAt_Must_Succeed(int[] source, Func public void ToArray_SelectorAt_MemoryPool_Must_Succeed(int[] source, Func selector) { // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var pool = ArrayPool.Shared; + var expected = source + .Select(selector) .ToArray(); // Act - using var result = source.AsMemory().AsValueEnumerable() + using var result = wrapped.AsValueEnumerable() .Select(selector) .ToArray(pool); // Assert - _ = result.Memory.Must() + _ = result.Must() + .BeEnumerableOf() .BeEqualTo(expected); } @@ -231,13 +247,14 @@ public void ToArray_SelectorAt_MemoryPool_Must_Succeed(int[] source, Func predicate, Func selector) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .Select(selector) .ToArray(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .ToArray(); @@ -256,20 +273,22 @@ public void ToArray_Predicate_Selector_Must_Succeed(int[] source, Func predicate, Func selector) { // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var pool = ArrayPool.Shared; + var expected = source + .Where(predicate) .Select(selector) .ToArray(); // Act - using var result = source.AsMemory().AsValueEnumerable() + using var result = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .ToArray(pool); // Assert - _ = result.Memory.Must() + _ = result.Must() + .BeEnumerableOf() .BeEqualTo(expected); } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs similarity index 77% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs index 085fc927b..d0d3786d0 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs @@ -17,12 +17,12 @@ public void ToArray_With_ValidData_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .ToArray(source); + var expected = source + .ToArray(); // Act - var result = ValueEnumerableExtensions - .ToArray, Wrap.Enumerator, int>(wrapped); + var result = wrapped + .ToArray, Wrap.Enumerator, int>(); // Assert _ = result.Must() @@ -39,8 +39,8 @@ public void ToArray_With_ValidData_Collections_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueCollection(source); - var expected = Enumerable - .ToArray(source); + var expected = source + .ToArray(); // Act var result = ValueEnumerableExtensions @@ -59,19 +59,20 @@ public void ToArray_With_ValidData_Collections_Must_Succeed(int[] source) public void ToArray_MemoryPool_Must_Succeed(int[] source) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .ToArray(source); + var expected = source + .ToArray(); // Act - using var result = ValueEnumerableExtensions - .ToArray, Wrap.Enumerator, int>(wrapped, pool); + using var result = wrapped + .ToArray, Wrap.Enumerator, int>(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -85,13 +86,13 @@ public void ToArray_Predicate_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ToArray(); // Assert @@ -107,21 +108,22 @@ public void ToArray_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToArray(); // Act - using var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + using var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -135,13 +137,13 @@ public void ToArray_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ToArray(); // Assert @@ -157,21 +159,22 @@ public void ToArray_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToArray(); // Act - using var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + using var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -185,13 +188,13 @@ public void ToArray_Selector_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ToArray(); // Assert @@ -207,21 +210,22 @@ public void ToArray_Selector_With_ValidData_Must_Succeed(int[] source, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToArray(); // Act - using var result = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + using var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -235,13 +239,13 @@ public void ToArray_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ToArray(); // Assert @@ -257,21 +261,22 @@ public void ToArray_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToArray(); // Act - using var result = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + using var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -285,14 +290,14 @@ public void ToArray_Predicate_Selector_With_ValidData_Must_Succeed(int[] source, // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .ToArray(); // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .ToArray(); @@ -309,23 +314,24 @@ public void ToArray_Predicate_Selector_With_ValidData_Must_Succeed(int[] source, public void ToArray_Predicate_Selector_MemoryPool_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .ToArray(); // Act - using var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + using var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ValueReadOnlyCollection.Tests.cs similarity index 69% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueReadOnlyCollection.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ValueReadOnlyCollection.Tests.cs index 9f984928a..c0975ed1b 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArray.ValueReadOnlyCollection.Tests.cs @@ -1,7 +1,7 @@ +using NetFabric.Assertive; using System; using System.Buffers; using System.Linq; -using NetFabric.Assertive; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToArray @@ -17,12 +17,12 @@ public void ToArray_With_ValidData_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .ToArray(wrapped); + var expected = source + .ToArray(); // Act - var result = ValueReadOnlyCollectionExtensions - .ToArray, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .ToArray(); // Assert _ = result.Must() @@ -39,12 +39,12 @@ public void ToArray_With_ValidData_Collections_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueCollection(source); - var expected = Enumerable - .ToArray(source); + var expected = source + .ToArray(); // Act - var result = ValueReadOnlyCollectionExtensions - .ToArray, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .ToArray(); // Assert _ = result.Must() @@ -59,19 +59,20 @@ public void ToArray_With_ValidData_Collections_Must_Succeed(int[] source) public void ToArray_MemoryPool_Must_Succeed(int[] source) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .ToArray(source); + var expected = source + .ToArray(); // Act - using var result = ValueEnumerableExtensions - .ToArray, Wrap.Enumerator, int>(wrapped, pool); + using var result = wrapped.AsValueEnumerable() + .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -85,13 +86,13 @@ public void ToArray_Predicate_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ToArray(); // Assert @@ -107,21 +108,22 @@ public void ToArray_Predicate_With_ValidData_Must_Succeed(int[] source, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToArray(); // Act - using var result = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + using var result = wrapped.AsValueEnumerable() + .Select(selector) .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -135,13 +137,13 @@ public void ToArray_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ToArray(); // Assert @@ -157,21 +159,22 @@ public void ToArray_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToArray(); // Act - using var result = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + using var result = wrapped.AsValueEnumerable() + .Select(selector) .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.Tests.cs similarity index 55% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.Tests.cs index 2f2d08914..e7cf9ee18 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.Tests.cs @@ -2,7 +2,6 @@ using System; using System.Buffers; using System.Linq; -using System.Threading; using System.Threading.Tasks; using Xunit; @@ -14,17 +13,18 @@ public class AsyncValueEnumerableTests [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_With_ValidData_Must_Succeed(int[] source) + public async Task ToArrayAsync_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .ToArray(source); + var expected = source + .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .ToArrayAsync, Wrap.AsyncEnumerator, int>(wrapped); + var result = await wrapped.AsAsyncValueEnumerable() + .ToArrayAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -36,22 +36,24 @@ public async ValueTask ToArrayAsync_With_ValidData_Must_Succeed(int[] source) [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_MemoryPool_Must_Succeed(int[] source) + public async Task ToArrayAsync_MemoryPool_Must_Succeed(int[] source) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .ToArray(source); + var expected = source + .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .ToArrayAsync, Wrap.AsyncEnumerator, int>(wrapped, pool); + var result = await wrapped.AsAsyncValueEnumerable() + .ToArrayAsync(pool) + .ConfigureAwait(false); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -60,19 +62,20 @@ public async ValueTask ToArrayAsync_MemoryPool_Must_Succeed(int[] source) [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task ToArrayAsync_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ToArrayAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ToArrayAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -84,24 +87,26 @@ public async ValueTask ToArrayAsync_Predicate_With_ValidData_Must_Succeed(int[] [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_Predicate_MemoryPool_Must_Succeed(int[] source, Func predicate) + public async Task ToArrayAsync_Predicate_MemoryPool_Must_Succeed(int[] source, Func predicate) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ToArrayAsync(pool); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ToArrayAsync(pool) + .ConfigureAwait(false); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -110,19 +115,20 @@ public async ValueTask ToArrayAsync_Predicate_MemoryPool_Must_Succeed(int[] sour [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task ToArrayAsync_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ToArrayAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ToArrayAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -134,24 +140,26 @@ public async ValueTask ToArrayAsync_PredicateAt_With_ValidData_Must_Succeed(int[ [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_PredicateAt_MemoryPool_Must_Succeed(int[] source, Func predicate) + public async Task ToArrayAsync_PredicateAt_MemoryPool_Must_Succeed(int[] source, Func predicate) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ToArrayAsync(pool); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ToArrayAsync(pool) + .ConfigureAwait(false); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -160,19 +168,20 @@ public async ValueTask ToArrayAsync_PredicateAt_MemoryPool_Must_Succeed(int[] so [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_Selector_With_ValidData_Must_Succeed(int[] source, Func selector) + public async Task ToArrayAsync_Selector_With_ValidData_Must_Succeed(int[] source, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ToArrayAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ToArrayAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -184,24 +193,26 @@ public async ValueTask ToArrayAsync_Selector_With_ValidData_Must_Succeed(int[] s [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_Selector_MemoryPool_Must_Succeed(int[] source, Func selector) + public async Task ToArrayAsync_Selector_MemoryPool_Must_Succeed(int[] source, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ToArrayAsync(pool); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ToArrayAsync(pool) + .ConfigureAwait(false); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -210,19 +221,20 @@ public async ValueTask ToArrayAsync_Selector_MemoryPool_Must_Succeed(int[] sourc [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func selector) + public async Task ToArrayAsync_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ToArrayAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ToArrayAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -234,24 +246,26 @@ public async ValueTask ToArrayAsync_SelectorAt_With_ValidData_Must_Succeed(int[] [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_SelectorAt_MemoryPool_Must_Succeed(int[] source, Func selector) + public async Task ToArrayAsync_SelectorAt_MemoryPool_Must_Succeed(int[] source, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ToArrayAsync(pool); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ToArrayAsync(pool) + .ConfigureAwait(false); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -261,21 +275,22 @@ public async ValueTask ToArrayAsync_SelectorAt_MemoryPool_Must_Succeed(int[] sou [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_Predicate_Selector_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) + public async Task ToArrayAsync_Predicate_Selector_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .ToArrayAsync(); + .ToArrayAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -287,26 +302,28 @@ public async ValueTask ToArrayAsync_Predicate_Selector_With_ValidData_Must_Succe [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask ToArrayAsync_Predicate_Selector_MemoryPool_Must_Succeed(int[] source, Func predicate, Func selector) + public async Task ToArrayAsync_Predicate_Selector_MemoryPool_Must_Succeed(int[] source, Func predicate, Func selector) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .ToArrayAsync(pool); + .ToArrayAsync(pool) + .ConfigureAwait(false); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ReadOnlyList.Tests.cs similarity index 93% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlyList.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ReadOnlyList.Tests.cs index 7f80d609f..024a5131e 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlyList.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ReadOnlyList.Tests.cs @@ -1,7 +1,7 @@ +using NetFabric.Assertive; using System; using System.Collections.Generic; using System.Linq; -using NetFabric.Assertive; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList @@ -16,8 +16,8 @@ public void ToList_Skip_Take_With_ReadOnlyList_ValidData_Must_Succeed(int[] sour { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .ToList(); @@ -42,8 +42,8 @@ public void ToList_Skip_Take_With_List_ValidData_Must_Succeed(int[] source, int { // Arrange var wrapped = Wrap.AsList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .ToList(); @@ -68,8 +68,8 @@ public void ToList_Skip_Take_Predicate_With_ValidData_Must_Succeed(int[] source, { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Where(predicate) .ToList(); @@ -97,8 +97,8 @@ public void ToList_Skip_Take_PredicateAt_With_ValidData_Must_Succeed(int[] sourc // Arrange var wrapped = Wrap .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Where(predicate) .ToList(); @@ -125,8 +125,8 @@ public void ToList_Skip_Take_Selector_With_ValidData_Must_Succeed(int[] source, { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Select(selector) .ToList(); @@ -153,8 +153,8 @@ public void ToList_Skip_Take_SelectorAt_With_ValidData_Must_Succeed(int[] source { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Select(selector) .ToList(); @@ -181,8 +181,8 @@ public void ToList_Skip_Take_Predicate_Selector_With_ValidData_Must_Succeed(int[ { // Arrange var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take) .Where(predicate) .Select(selector) diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ReadOnlySpan.Tests.cs similarity index 76% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlySpan.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ReadOnlySpan.Tests.cs index 599dd8fc6..61d34ec74 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlySpan.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ReadOnlySpan.Tests.cs @@ -1,7 +1,7 @@ +using NetFabric.Assertive; using System; using System.Collections.Generic; using System.Linq; -using NetFabric.Assertive; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList @@ -15,12 +15,13 @@ public class ReadOnlySpanTests public void ToList_With_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .ToList(source); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .ToList(); // Act - var result = ArrayExtensions - .ToList((ReadOnlySpan)source.AsSpan()); + var result = wrapped.AsValueEnumerable() + .ToList(); // Assert _ = result.Must() @@ -36,13 +37,14 @@ public void ToList_With_Must_Succeed(int[] source) public void ToList_With_Predicate_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .ToList(); // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .ToList(); // Assert @@ -59,13 +61,14 @@ public void ToList_With_Predicate_Must_Succeed(int[] source, Func pre public void ToList_With_PredicateAt_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .ToList(); // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .ToList(); // Assert @@ -82,13 +85,14 @@ public void ToList_With_PredicateAt_Must_Succeed(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .ToList(); // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ToList(); // Assert @@ -105,13 +109,14 @@ public void ToList_With_Selector_Must_Succeed(int[] source, Func se public void ToList_With_SelectorAt_Must_Succeed(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .ToList(); // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ToList(); // Assert @@ -128,14 +133,15 @@ public void ToList_With_SelectorAt_Must_Succeed(int[] source, Func predicate, Func selector) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .Select(selector) .ToList(); // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector) .ToList(); diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ValueEnumerable.Tests.cs similarity index 84% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ValueEnumerable.Tests.cs index 5904ed0cf..2f243f2f0 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ValueEnumerable.Tests.cs @@ -17,12 +17,12 @@ public void ToList_With_ValidData_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .ToList(source); + var expected = source + .ToList(); // Act - var result = ValueEnumerableExtensions - .ToList, Wrap.Enumerator, int>(wrapped); + var result = wrapped + .ToList, Wrap.Enumerator, int>(); // Assert _ = result.Must() @@ -40,8 +40,8 @@ public void ToList_With_ValidData_Collections_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueCollection(source); - var expected = Enumerable - .ToList(source); + var expected = source + .ToList(); // Act var result = ValueEnumerableExtensions @@ -63,13 +63,13 @@ public void ToList_Predicate_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ToList(); // Assert @@ -88,13 +88,13 @@ public void ToList_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ToList(); // Assert @@ -113,13 +113,13 @@ public void ToList_Selector_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ToList(); // Assert @@ -138,13 +138,13 @@ public void ToList_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ToList(); // Assert @@ -164,14 +164,14 @@ public void ToList_Predicate_Selector_With_ValidData_Must_Succeed(int[] source, // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .ToList(); // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .ToList(); diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ValueReadOnlyCollection.Tests.cs similarity index 75% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ValueReadOnlyCollection.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ValueReadOnlyCollection.Tests.cs index df4f94d2e..9a2c667e7 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToList.ValueReadOnlyCollection.Tests.cs @@ -1,7 +1,7 @@ +using NetFabric.Assertive; using System; using System.Collections.Generic; using System.Linq; -using NetFabric.Assertive; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList @@ -17,12 +17,12 @@ public void ToList_With_ValidData_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .ToList(wrapped); + var expected = wrapped + .ToList(); // Act - var result = ValueReadOnlyCollectionExtensions - .ToList, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .ToList(); // Assert _ = result.Must() @@ -40,12 +40,12 @@ public void ToList_With_ValidData_Collections_Must_Succeed(int[] source) // Arrange var wrapped = Wrap .AsValueCollection(source); - var expected = Enumerable - .ToList(source); + var expected = source + .ToList(); // Act - var result = ValueReadOnlyCollectionExtensions - .ToList, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .ToList(); // Assert _ = result.Must() @@ -63,13 +63,13 @@ public void ToList_Predicate_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ToList(); // Assert @@ -88,13 +88,13 @@ public void ToList_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ToList(); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToListAsync.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToListAsync.AsyncValueEnumerable.Tests.cs similarity index 61% rename from NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToListAsync.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToListAsync.AsyncValueEnumerable.Tests.cs index 5e6ce887d..921eaca63 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToListAsync.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Conversion/ToList/ToListAsync.AsyncValueEnumerable.Tests.cs @@ -13,17 +13,18 @@ public class AsyncValueEnumerableTests [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ToListAsync_With_ValidData_Must_Succeed(int[] source) + public async Task ToListAsync_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .ToList(source); + var expected = source + .ToList(); // Act - var result = await AsyncValueEnumerableExtensions - .ToListAsync, Wrap.AsyncEnumerator, int>(wrapped); + var result = await wrapped.AsAsyncValueEnumerable() + .ToListAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -36,19 +37,20 @@ public async ValueTask ToListAsync_With_ValidData_Must_Succeed(int[] source) [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public async ValueTask ToListAsync_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task ToListAsync_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToList(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ToListAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ToListAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -61,19 +63,20 @@ public async ValueTask ToListAsync_Predicate_With_ValidData_Must_Succeed(int[] s [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public async ValueTask ToListAsync_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task ToListAsync_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToList(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ToListAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ToListAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -86,19 +89,20 @@ public async ValueTask ToListAsync_PredicateAt_With_ValidData_Must_Succeed(int[] [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask ToListAsync_Selector_With_ValidData_Must_Succeed(int[] source, Func selector) + public async Task ToListAsync_Selector_With_ValidData_Must_Succeed(int[] source, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToList(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ToListAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ToListAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -111,19 +115,20 @@ public async ValueTask ToListAsync_Selector_With_ValidData_Must_Succeed(int[] so [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public async ValueTask ToListAsync_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func selector) + public async Task ToListAsync_SelectorAt_With_ValidData_Must_Succeed(int[] source, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToList(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ToListAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ToListAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -137,21 +142,22 @@ public async ValueTask ToListAsync_SelectorAt_With_ValidData_Must_Succeed(int[] [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask ToListAsync_Predicate_Selector_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) + public async Task ToListAsync_Predicate_Selector_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .ToList(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .ToListAsync(); + .ToListAsync() + .ConfigureAwait(false); // Assert _ = result.Must() diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt.TestData.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt.TestData.cs new file mode 100644 index 000000000..4b83f55e0 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt.TestData.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + public static TheoryData ElementAtOutOfRange => + new() + { + { Array.Empty(), -1 }, + { Array.Empty(), 0 }, + { Array.Empty(), 1 }, + { new[] { 1 }, -1 }, + { new[] { 1 }, 1 }, + { new[] { 1, 2, 3, 4, 5 }, -1 }, + { new[] { 1, 2, 3, 4, 5 }, 5 } + }; + + public static TheoryData ElementAt => + new() + { + { new[] { 1 }, 0}, + { new[] { 1, 2, 3, 4, 5 }, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 2 }, + { new[] { 1, 2, 3, 4, 5 }, 4 } + }; + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.Memory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ReadOnlyList.Tests.cs similarity index 80% rename from NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.Memory.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ReadOnlyList.Tests.cs index 4d6a0efe0..799899e46 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.Memory.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ReadOnlyList.Tests.cs @@ -5,7 +5,7 @@ namespace NetFabric.Hyperlinq.UnitTests.Element.ElementAt { - public class MemoryTests + public class ReadOnlyListTests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -14,11 +14,13 @@ public class MemoryTests public void ElementAt_With_OutOfRange_Must_Return_None(int[] source) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var optionNegative = source.AsMemory().AsValueEnumerable() + var optionNegative = wrapped.AsValueEnumerable() .ElementAt(-1); - var optionTooLarge = source.AsMemory().AsValueEnumerable() + var optionTooLarge = wrapped.AsValueEnumerable() .ElementAt(source.Length); // Assert @@ -38,11 +40,13 @@ public void ElementAt_With_ValidData_Must_Return_Some(int[] source) for (var index = 0; index < source.Length; index++) { // Arrange - var expected = Enumerable - .ElementAt(source, index); + var wrapped = Wrap + .AsValueList(source); + var expected = source + .ElementAt(index); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .ElementAt(index); // Assert @@ -59,12 +63,14 @@ public void ElementAt_With_ValidData_Must_Return_Some(int[] source) public void ElementAt_Predicate_With_OutOfRange_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var optionNegative = source.AsMemory().AsValueEnumerable() + var optionNegative = wrapped.AsValueEnumerable() .Where(predicate) .ElementAt(-1); - var optionTooLarge = source.AsMemory().AsValueEnumerable() + var optionTooLarge = wrapped.AsValueEnumerable() .Where(predicate) .ElementAt(source.Length); @@ -83,14 +89,16 @@ public void ElementAt_Predicate_With_OutOfRange_Must_Return_None(int[] source, F public void ElementAt_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Where(predicate) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .ElementAt(index); @@ -108,12 +116,14 @@ public void ElementAt_Predicate_With_ValidData_Must_Return_Some(int[] source, Fu public void ElementAt_PredicateAt_With_OutOfRange_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var optionNegative = source.AsMemory().AsValueEnumerable() + var optionNegative = wrapped.AsValueEnumerable() .Where(predicate) .ElementAt(-1); - var optionTooLarge = source.AsMemory().AsValueEnumerable() + var optionTooLarge = wrapped.AsValueEnumerable() .Where(predicate) .ElementAt(source.Length); @@ -132,14 +142,16 @@ public void ElementAt_PredicateAt_With_OutOfRange_Must_Return_None(int[] source, public void ElementAt_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Where(predicate) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .ElementAt(index); @@ -157,12 +169,14 @@ public void ElementAt_PredicateAt_With_ValidData_Must_Return_Some(int[] source, public void ElementAt_Selector_With_OutOfRange_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var optionNegative = source.AsMemory().AsValueEnumerable() + var optionNegative = wrapped.AsValueEnumerable() .Select(selector) .ElementAt(-1); - var optionTooLarge = source.AsMemory().AsValueEnumerable() + var optionTooLarge = wrapped.AsValueEnumerable() .Select(selector) .ElementAt(source.Length); @@ -181,14 +195,16 @@ public void ElementAt_Selector_With_OutOfRange_Must_Return_None(int[] source, Fu public void ElementAt_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .ElementAt(index); @@ -206,12 +222,14 @@ public void ElementAt_Selector_With_ValidData_Must_Return_Some(int[] source, Fun public void ElementAt_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var optionNegative = source.AsMemory().AsValueEnumerable() + var optionNegative = wrapped.AsValueEnumerable() .Select(selector) .ElementAt(-1); - var optionTooLarge = source.AsMemory().AsValueEnumerable() + var optionTooLarge = wrapped.AsValueEnumerable() .Select(selector) .ElementAt(source.Length); @@ -230,14 +248,16 @@ public void ElementAt_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, public void ElementAt_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .ElementAt(index); @@ -255,13 +275,15 @@ public void ElementAt_SelectorAt_With_ValidData_Must_Return_Some(int[] source, F public void ElementAt_Predicate_Selector_With_OutOfRange_Must_Return_None(int[] source, Func predicate, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var optionNegative = source.AsMemory().AsValueEnumerable() + var optionNegative = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .ElementAt(-1); - var optionTooLarge = source.AsMemory().AsValueEnumerable() + var optionTooLarge = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .ElementAt(source.Length); @@ -281,15 +303,17 @@ public void ElementAt_Predicate_Selector_With_OutOfRange_Must_Return_None(int[] public void ElementAt_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Where(predicate) .Select(selector) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .ElementAt(index); diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ReadOnlySpan.Tests.cs similarity index 76% rename from NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ReadOnlySpan.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ReadOnlySpan.Tests.cs index 3fd03aaa4..07da1cf48 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ReadOnlySpan.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ReadOnlySpan.Tests.cs @@ -14,12 +14,13 @@ public class ReadOnlySpanTests public void ElementAt_With_OutOfRange_Must_Return_None(int[] source) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var optionNegative = ArrayExtensions - .ElementAt((ReadOnlySpan)source.AsSpan(), -1); - var optionTooLarge = ArrayExtensions - .ElementAt((ReadOnlySpan)source.AsSpan(), source.Length); + var optionNegative = wrapped.AsValueEnumerable() + .ElementAt(-1); + var optionTooLarge = wrapped.AsValueEnumerable() + .ElementAt(source.Length); // Assert _ = optionNegative.Must() @@ -38,12 +39,13 @@ public void ElementAt_With_ValidData_Must_Return_Some(int[] source) for (var index = 0; index < source.Length; index++) { // Arrange - var expected = Enumerable - .ElementAt(source, index); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .ElementAt(index); // Act - var result = ArrayExtensions - .ElementAt((ReadOnlySpan)source.AsSpan(), index); + var result = wrapped.AsValueEnumerable() + .ElementAt(index); // Assert _ = result.Match( @@ -59,13 +61,14 @@ public void ElementAt_With_ValidData_Must_Return_Some(int[] source) public void ElementAt_Predicate_With_OutOfRange_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var optionNegative = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var optionNegative = wrapped.AsValueEnumerable() + .Where(predicate) .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var optionTooLarge = wrapped.AsValueEnumerable() + .Where(predicate) .ElementAt(source.Length); // Assert @@ -83,15 +86,16 @@ public void ElementAt_Predicate_With_OutOfRange_Must_Return_None(int[] source, F public void ElementAt_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .ElementAt(index); // Assert @@ -108,13 +112,14 @@ public void ElementAt_Predicate_With_ValidData_Must_Return_Some(int[] source, Fu public void ElementAt_PredicateAt_With_OutOfRange_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var optionNegative = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var optionNegative = wrapped.AsValueEnumerable() + .Where(predicate) .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var optionTooLarge = wrapped.AsValueEnumerable() + .Where(predicate) .ElementAt(source.Length); // Assert @@ -132,15 +137,16 @@ public void ElementAt_PredicateAt_With_OutOfRange_Must_Return_None(int[] source, public void ElementAt_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .ElementAt(index); // Assert @@ -157,13 +163,14 @@ public void ElementAt_PredicateAt_With_ValidData_Must_Return_Some(int[] source, public void ElementAt_Selector_With_OutOfRange_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var optionNegative = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) + var optionNegative = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) + var optionTooLarge = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(source.Length); // Assert @@ -181,15 +188,16 @@ public void ElementAt_Selector_With_OutOfRange_Must_Return_None(int[] source, Fu public void ElementAt_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(index); // Assert @@ -206,13 +214,14 @@ public void ElementAt_Selector_With_ValidData_Must_Return_Some(int[] source, Fun public void ElementAt_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var optionNegative = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) + var optionNegative = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) + var optionTooLarge = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(source.Length); // Assert @@ -230,15 +239,16 @@ public void ElementAt_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, public void ElementAt_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(index); // Assert @@ -255,14 +265,15 @@ public void ElementAt_SelectorAt_With_ValidData_Must_Return_Some(int[] source, F public void ElementAt_Predicate_Selector_With_OutOfRange_Must_Return_None(int[] source, Func predicate, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var optionNegative = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var optionNegative = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector) .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var optionTooLarge = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector) .ElementAt(source.Length); @@ -281,16 +292,17 @@ public void ElementAt_Predicate_Selector_With_OutOfRange_Must_Return_None(int[] public void ElementAt_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .Select(selector) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector) .ElementAt(index); diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ValueEnumerable.Tests.cs similarity index 83% rename from NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ValueEnumerable.Tests.cs index 0561f4e94..421132231 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ValueEnumerable.Tests.cs @@ -18,10 +18,10 @@ public void ElementAt_With_OutOfRange_Must_Return_None(int[] source) .AsValueEnumerable(source); // Act - var optionNegative = ValueEnumerableExtensions - .ElementAt, Wrap.Enumerator, int>(wrapped, -1); - var optionTooLarge = ValueEnumerableExtensions - .ElementAt, Wrap.Enumerator, int>(wrapped, source.Length); + var optionNegative = wrapped + .ElementAt, Wrap.Enumerator, int>(-1); + var optionTooLarge = wrapped + .ElementAt, Wrap.Enumerator, int>(source.Length); // Assert _ = optionNegative.Must() @@ -42,12 +42,12 @@ public void ElementAt_With_ValidData_Must_Return_Some(int[] source) // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .ElementAt(source, index); + var expected = source + .ElementAt(index); // Act - var result = ValueEnumerableExtensions - .ElementAt, Wrap.Enumerator, int>(wrapped, index); + var result = wrapped + .ElementAt, Wrap.Enumerator, int>(index); // Assert _ = result.Match( @@ -67,11 +67,11 @@ public void ElementAt_Predicate_With_OutOfRange_Must_Return_None(int[] source, F .AsValueEnumerable(source); // Act - var optionNegative = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var optionNegative = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ElementAt(-1); - var optionTooLarge = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var optionTooLarge = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ElementAt(source.Length); // Assert @@ -91,15 +91,15 @@ public void ElementAt_Predicate_With_ValidData_Must_Return_Some(int[] source, Fu // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ElementAt(index); // Assert @@ -120,11 +120,11 @@ public void ElementAt_PredicateAt_With_OutOfRange_Must_Return_None(int[] source, .AsValueEnumerable(source); // Act - var optionNegative = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var optionNegative = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ElementAt(-1); - var optionTooLarge = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var optionTooLarge = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ElementAt(source.Length); // Assert @@ -144,15 +144,15 @@ public void ElementAt_PredicateAt_With_ValidData_Must_Return_Some(int[] source, // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .ElementAt(index); // Assert @@ -173,11 +173,11 @@ public void ElementAt_Selector_With_OutOfRange_Must_Return_None(int[] source, Fu .AsValueEnumerable(source); // Act - var optionNegative = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var optionNegative = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ElementAt(-1); - var optionTooLarge = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var optionTooLarge = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ElementAt(source.Length); // Assert @@ -197,15 +197,15 @@ public void ElementAt_Selector_With_ValidData_Must_Return_Some(int[] source, Fun // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ElementAt(index); // Assert @@ -226,11 +226,11 @@ public void ElementAt_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, .AsValueEnumerable(source); // Act - var optionNegative = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var optionNegative = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ElementAt(-1); - var optionTooLarge = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var optionTooLarge = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ElementAt(source.Length); // Assert @@ -250,15 +250,15 @@ public void ElementAt_SelectorAt_With_ValidData_Must_Return_Some(int[] source, F // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .ElementAt(index); // Assert @@ -279,12 +279,12 @@ public void ElementAt_Predicate_Selector_With_OutOfRange_Must_Return_None(int[] .AsValueEnumerable(source); // Act - var optionNegative = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var optionNegative = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .ElementAt(-1); - var optionTooLarge = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var optionTooLarge = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .ElementAt(source.Length); @@ -305,16 +305,16 @@ public void ElementAt_Predicate_Selector_With_ValidData_Must_Return_Some(int[] s // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .ElementAt(index); diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ValueReadOnlyCollection.Tests.cs similarity index 72% rename from NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ValueReadOnlyCollection.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ValueReadOnlyCollection.Tests.cs index 659cbc4bf..5020adab6 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAt.ValueReadOnlyCollection.Tests.cs @@ -18,10 +18,10 @@ public void ElementAt_With_OutOfRange_Must_Return_None(int[] source) .AsValueReadOnlyCollection(source); // Act - var optionNegative = ValueReadOnlyCollectionExtensions - .ElementAt, Wrap.Enumerator, int>(wrapped, -1); - var optionTooLarge = ValueReadOnlyCollectionExtensions - .ElementAt, Wrap.Enumerator, int>(wrapped, source.Length); + var optionNegative = wrapped.AsValueEnumerable() + .ElementAt(-1); + var optionTooLarge = wrapped.AsValueEnumerable() + .ElementAt(source.Length); // Assert _ = optionNegative.Must() @@ -42,12 +42,12 @@ public void ElementAt_With_ValidData_Must_Return_Some(int[] source) // Arrange var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .ElementAt(source, index); + var expected = source + .ElementAt(index); // Act - var result = ValueReadOnlyCollectionExtensions - .ElementAt, Wrap.Enumerator, int>(wrapped, index); + var result = wrapped.AsValueEnumerable() + .ElementAt(index); // Assert _ = result.Match( @@ -67,11 +67,11 @@ public void ElementAt_Selector_With_OutOfRange_Must_Return_None(int[] source, Fu .AsValueReadOnlyCollection(source); // Act - var optionNegative = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var optionNegative = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(-1); - var optionTooLarge = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var optionTooLarge = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(source.Length); // Assert @@ -90,15 +90,15 @@ public void ElementAt_Selector_With_ValidData_Must_Return_Some(int[] source, Fun { // Arrange var wrapped = Wrap.AsValueReadOnlyCollection(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(index); // Assert @@ -119,11 +119,11 @@ public void ElementAt_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, .AsValueReadOnlyCollection(source); // Act - var optionNegative = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var optionNegative = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(-1); - var optionTooLarge = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var optionTooLarge = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(source.Length); // Assert @@ -143,15 +143,15 @@ public void ElementAt_SelectorAt_With_ValidData_Must_Return_Some(int[] source, F // Arrange var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .ElementAt(index); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.Tests.cs similarity index 62% rename from NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.Tests.cs index dc6f77f7d..11dd52718 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.Tests.cs @@ -19,10 +19,12 @@ public async void ElementAtAsync_With_OutOfRange_Must_Return_None(int[] source) .AsAsyncValueEnumerable(source); // Act - var optionNegative = await AsyncValueEnumerableExtensions - .ElementAtAsync, Wrap.AsyncEnumerator, int>(wrapped, -1); - var optionTooLarge = await AsyncValueEnumerableExtensions - .ElementAtAsync, Wrap.AsyncEnumerator, int>(wrapped, source.Length); + var optionNegative = await wrapped.AsAsyncValueEnumerable() + .ElementAtAsync(-1) + .ConfigureAwait(false); + var optionTooLarge = await wrapped.AsAsyncValueEnumerable() + .ElementAtAsync(source.Length) + .ConfigureAwait(false); // Assert _ = optionNegative.Must() @@ -36,19 +38,20 @@ public async void ElementAtAsync_With_OutOfRange_Must_Return_None(int[] source) [Theory] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ElementAtAsync_With_ValidData_Must_Return_Some(int[] source) + public async Task ElementAtAsync_With_ValidData_Must_Return_Some(int[] source) { var wrapped = Wrap .AsAsyncValueEnumerable(source); for (var index = 0; index < source.Length; index++) { // Arrange - var expected = Enumerable - .ElementAt(source, index); + var expected = source + .ElementAt(index); // Act - var result = await AsyncValueEnumerableExtensions - .ElementAtAsync, Wrap.AsyncEnumerator, int>(wrapped, index); + var result = await wrapped.AsAsyncValueEnumerable() + .ElementAtAsync(index) + .ConfigureAwait(false); // Assert _ = result.Match( @@ -68,12 +71,14 @@ public async void ElementAtAsync_Predicate_With_OutOfRange_Must_Return_None(int[ .AsAsyncValueEnumerable(source); // Act - var optionNegative = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ElementAtAsync(-1); - var optionTooLarge = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ElementAtAsync(source.Length); + var optionNegative = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ElementAtAsync(-1) + .ConfigureAwait(false); + var optionTooLarge = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ElementAtAsync(source.Length) + .ConfigureAwait(false); // Assert _ = optionNegative.Must() @@ -87,21 +92,22 @@ public async void ElementAtAsync_Predicate_With_OutOfRange_Must_Return_None(int[ [Theory] [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public async ValueTask ElementAtAsync_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) + public async Task ElementAtAsync_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ElementAtAsync(index); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ElementAtAsync(index) + .ConfigureAwait(false); // Assert _ = result.Match( @@ -121,12 +127,14 @@ public async void ElementAtAsync_PredicateAt_With_OutOfRange_Must_Return_None(in .AsAsyncValueEnumerable(source); // Act - var optionNegative = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ElementAtAsync(-1); - var optionTooLarge = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ElementAtAsync(source.Length); + var optionNegative = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ElementAtAsync(-1) + .ConfigureAwait(false); + var optionTooLarge = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ElementAtAsync(source.Length) + .ConfigureAwait(false); // Assert _ = optionNegative.Must() @@ -140,20 +148,21 @@ public async void ElementAtAsync_PredicateAt_With_OutOfRange_Must_Return_None(in [Theory] [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public async ValueTask ElementAtAsync_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) + public async Task ElementAtAsync_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .ElementAtAsync(index); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .ElementAtAsync(index) + .ConfigureAwait(false); // Assert _ = result.Match( @@ -173,12 +182,14 @@ public async void ElementAtAsync_Selector_With_OutOfRange_Must_Return_None(int[] .AsAsyncValueEnumerable(source); // Act - var optionNegative = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ElementAtAsync(-1); - var optionTooLarge = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ElementAtAsync(source.Length); + var optionNegative = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ElementAtAsync(-1) + .ConfigureAwait(false); + var optionTooLarge = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ElementAtAsync(source.Length) + .ConfigureAwait(false); // Assert _ = optionNegative.Must() @@ -192,20 +203,21 @@ public async void ElementAtAsync_Selector_With_OutOfRange_Must_Return_None(int[] [Theory] [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask ElementAtAsync_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) + public async Task ElementAtAsync_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ElementAtAsync(index); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ElementAtAsync(index) + .ConfigureAwait(false); // Assert _ = result.Match( @@ -225,12 +237,14 @@ public async void ElementAtAsync_SelectorAt_With_OutOfRange_Must_Return_None(int .AsAsyncValueEnumerable(source); // Act - var optionNegative = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ElementAtAsync(-1); - var optionTooLarge = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ElementAtAsync(source.Length); + var optionNegative = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ElementAtAsync(-1) + .ConfigureAwait(false); + var optionTooLarge = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ElementAtAsync(source.Length) + .ConfigureAwait(false); // Assert _ = optionNegative.Must() @@ -244,21 +258,22 @@ public async void ElementAtAsync_SelectorAt_With_OutOfRange_Must_Return_None(int [Theory] [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public async ValueTask ElementAtAsync_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) + public async Task ElementAtAsync_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .ToList(); for (var index = 0; index < source.Length; index++) { // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .ElementAtAsync(index); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .ElementAtAsync(index) + .ConfigureAwait(false); // Assert _ = result.Match( @@ -278,14 +293,16 @@ public async void ElementAtAsync_Predicate_Selector_With_OutOfRange_Must_Return_ .AsAsyncValueEnumerable(source); // Act - var optionNegative = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var optionNegative = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .ElementAtAsync(-1); - var optionTooLarge = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + .ElementAtAsync(-1) + .ConfigureAwait(false); + var optionTooLarge = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .ElementAtAsync(source.Length); + .ElementAtAsync(source.Length) + .ConfigureAwait(false); // Assert _ = optionNegative.Must() @@ -299,23 +316,24 @@ public async void ElementAtAsync_Predicate_Selector_With_OutOfRange_Must_Return_ [Theory] [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask ElementAtAsync_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) + public async Task ElementAtAsync_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .ToList(); for (var index = 0; index < expected.Count; index++) { // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .ElementAtAsync(index); + .ElementAtAsync(index) + .ConfigureAwait(false); // Assert _ = result.Match( @@ -324,4 +342,4 @@ public async ValueTask ElementAtAsync_Predicate_Selector_With_ValidData_Must_Ret } } } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/First.Memory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ReadOnlyList.Tests.cs similarity index 73% rename from NetFabric.Hyperlinq.UnitTests/Element/First/First.Memory.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ReadOnlyList.Tests.cs index 9e0ee7f4e..8e497a8ab 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/First.Memory.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ReadOnlyList.Tests.cs @@ -5,16 +5,18 @@ namespace NetFabric.Hyperlinq.UnitTests.Element.First { - public class MemoryTests + public class ReadOnlyListTests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] public void First_With_Empty_Must_Return_None(int[] source) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .First(); // Assert @@ -29,16 +31,18 @@ public void First_With_Empty_Must_Return_None(int[] source) public void First_With_ValidData_Must_Return_Some(int[] source) { // Arrange - var expected = Enumerable - .First(source); + var wrapped = Wrap + .AsValueList(source); + var expected = source + .First(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .First(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -47,9 +51,11 @@ public void First_With_ValidData_Must_Return_Some(int[] source) public void First_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .First(); @@ -65,17 +71,19 @@ public void First_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .First(source, predicate); + var wrapped = Wrap + .AsValueList(source); + var expected = source + .First(predicate); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .First(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -84,10 +92,12 @@ public void First_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = source.AsMemory().AsValueEnumerable() - .Where (predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .First(); // Assert @@ -102,18 +112,20 @@ public void First_PredicateAt_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Where(predicate) .First(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .First(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -122,9 +134,11 @@ public void First_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func public void First_Selector_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .First(); @@ -140,18 +154,20 @@ public void First_Selector_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Select(selector) .First(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .First(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -160,9 +176,11 @@ public void First_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .First(); @@ -178,18 +196,20 @@ public void First_SelectorAt_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Select(selector) .First(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .First(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -198,9 +218,11 @@ public void First_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func< public void First_Predicate_Selector_With_Empty_Must_Return_None(int[] source, Func predicate, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .First(); @@ -217,21 +239,23 @@ public void First_Predicate_Selector_With_Empty_Must_Return_None(int[] source, F public void First_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Where(predicate) .Select(selector) .First(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .First(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ReadOnlySpan.Tests.cs similarity index 74% rename from NetFabric.Hyperlinq.UnitTests/Element/First/First.ReadOnlyMemory.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ReadOnlySpan.Tests.cs index fd8d7ab06..8e609ef94 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ReadOnlySpan.Tests.cs @@ -5,16 +5,17 @@ namespace NetFabric.Hyperlinq.UnitTests.Element.First { - public class ReadOnlyMemoryTests + public class ReadOnlySpanTests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] public void First_With_Empty_Must_Return_None(int[] source) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .First(); // Assert @@ -29,11 +30,12 @@ public void First_With_Empty_Must_Return_None(int[] source) public void First_With_ValidData_Must_Return_Some(int[] source) { // Arrange - var expected = Enumerable - .First(source); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .First(); // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .First(); // Assert @@ -47,10 +49,11 @@ public void First_With_ValidData_Must_Return_Some(int[] source) public void First_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .First(); // Assert @@ -65,12 +68,13 @@ public void First_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .First(source, predicate); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .First(predicate); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .First(); // Assert @@ -84,10 +88,11 @@ public void First_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .First(); // Assert @@ -102,13 +107,14 @@ public void First_PredicateAt_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .First(); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .First(); // Assert @@ -122,10 +128,11 @@ public void First_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func public void First_Selector_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .First(); // Assert @@ -140,13 +147,14 @@ public void First_Selector_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .First(); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .First(); // Assert @@ -160,10 +168,11 @@ public void First_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .First(); // Assert @@ -178,13 +187,14 @@ public void First_SelectorAt_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .First(); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .First(); // Assert @@ -198,10 +208,11 @@ public void First_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func< public void First_Predicate_Selector_With_Empty_Must_Return_None(int[] source, Func predicate, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector) .First(); @@ -217,14 +228,15 @@ public void First_Predicate_Selector_With_Empty_Must_Return_None(int[] source, F public void First_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .Select(selector) .First(); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector) .First(); @@ -234,4 +246,4 @@ public void First_Predicate_Selector_With_ValidData_Must_Return_Some(int[] sourc () => throw new Exception()); } } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ValueEnumerable.Tests.cs similarity index 83% rename from NetFabric.Hyperlinq.UnitTests/Element/First/First.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ValueEnumerable.Tests.cs index 364a06132..081c29cd5 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ValueEnumerable.Tests.cs @@ -16,8 +16,8 @@ public void First_With_Empty_Must_Return_None(int[] source) .AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .First, Wrap.Enumerator, int>(wrapped); + var result = wrapped + .First, Wrap.Enumerator, int>(); // Assert _ = result.Must() @@ -33,12 +33,12 @@ public void First_With_ValidData_Must_Return_Some(int[] source) // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .First(source); + var expected = source + .First(); // Act - var result = ValueEnumerableExtensions - .First, Wrap.Enumerator, int>(wrapped); + var result = wrapped + .First, Wrap.Enumerator, int>(); // Assert _ = result.Match( @@ -55,8 +55,8 @@ public void First_Predicate_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .First(); // Assert @@ -73,12 +73,12 @@ public void First_Predicate_With_ValidData_Must_Return_Some(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .First(); // Assert @@ -96,8 +96,8 @@ public void First_PredicateAt_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .First(); // Assert @@ -114,13 +114,13 @@ public void First_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .First(); // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .First(); // Assert @@ -138,8 +138,8 @@ public void First_Selector_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .First(); // Assert @@ -156,13 +156,13 @@ public void First_Selector_With_ValidData_Must_Return_Some(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .First(); // Assert @@ -180,8 +180,8 @@ public void First_SelectorAt_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .First(); // Assert @@ -198,13 +198,13 @@ public void First_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func< // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .First(); // Act - var result = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .First(); // Assert @@ -222,8 +222,8 @@ public void First_Predicate_Selector_With_Empty_Must_Return_None(int[] source, F .AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .First(); @@ -241,14 +241,14 @@ public void First_Predicate_Selector_With_ValidData_Must_Return_Some(int[] sourc // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .First(); // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .First(); diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ValueReadOnlyCollection.Tests.cs similarity index 73% rename from NetFabric.Hyperlinq.UnitTests/Element/First/First.ValueReadOnlyCollection.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ValueReadOnlyCollection.Tests.cs index c5a3ef19c..f6b0b59ba 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/First.ValueReadOnlyCollection.Tests.cs @@ -16,8 +16,8 @@ public void First_With_Empty_Must_Return_None(int[] source) .AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .First, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .First(); // Assert _ = result.Must() @@ -33,12 +33,12 @@ public void First_With_ValidData_Must_Return_Some(int[] source) // Arrange var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .First(source); + var expected = source + .First(); // Act - var result = ValueReadOnlyCollectionExtensions - .First, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .First(); // Assert _ = result.Match( @@ -55,8 +55,8 @@ public void First_Selector_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .First(); // Assert @@ -73,13 +73,13 @@ public void First_Selector_With_ValidData_Must_Return_Some(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .First(); // Assert @@ -97,8 +97,8 @@ public void First_SelectorAt_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .First(); // Assert @@ -115,13 +115,13 @@ public void First_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func< // Arrange var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .First(); // Act - var result = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .First(); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/FirstAsync.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/FirstAsync.AsyncValueEnumerable.Tests.cs similarity index 63% rename from NetFabric.Hyperlinq.UnitTests/Element/First/FirstAsync.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/First/FirstAsync.AsyncValueEnumerable.Tests.cs index 4dc955593..dfd6668a8 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/FirstAsync.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/First/FirstAsync.AsyncValueEnumerable.Tests.cs @@ -17,8 +17,9 @@ public async void FirstAsync_With_Empty_Must_Return_None(int[] source) .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .FirstAsync, Wrap.AsyncEnumerator, int>(wrapped); + var result = await wrapped.AsAsyncValueEnumerable() + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -29,17 +30,18 @@ public async void FirstAsync_With_Empty_Must_Return_None(int[] source) [Theory] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask FirstAsync_With_ValidData_Must_Return_Some(int[] source) + public async Task FirstAsync_With_ValidData_Must_Return_Some(int[] source) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .First(source); + var expected = source + .First(); // Act - var result = await AsyncValueEnumerableExtensions - .FirstAsync, Wrap.AsyncEnumerator, int>(wrapped); + var result = await wrapped.AsAsyncValueEnumerable() + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Match( @@ -56,9 +58,10 @@ public async void FirstAsync_Predicate_With_Empty_Must_Return_None(int[] source, .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .FirstAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -69,18 +72,19 @@ public async void FirstAsync_Predicate_With_Empty_Must_Return_None(int[] source, [Theory] [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public async ValueTask FirstAsync_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) + public async Task FirstAsync_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .First(source, predicate); + var expected = source + .First(predicate); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .FirstAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Match( @@ -97,9 +101,10 @@ public async void FirstAsync_PredicateAt_With_Empty_Must_Return_None(int[] sourc .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .FirstAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -110,19 +115,20 @@ public async void FirstAsync_PredicateAt_With_Empty_Must_Return_None(int[] sourc [Theory] [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public async ValueTask FirstAsync_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) + public async Task FirstAsync_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .First(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .FirstAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Match( @@ -139,9 +145,10 @@ public async void FirstAsync_Selector_With_Empty_Must_Return_None(int[] source, .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .FirstAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -152,19 +159,20 @@ public async void FirstAsync_Selector_With_Empty_Must_Return_None(int[] source, [Theory] [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask FirstAsync_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) + public async Task FirstAsync_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .First(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .FirstAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Match( @@ -181,9 +189,10 @@ public async void FirstAsync_SelectorAt_With_Empty_Must_Return_None(int[] source .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .FirstAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -194,19 +203,20 @@ public async void FirstAsync_SelectorAt_With_Empty_Must_Return_None(int[] source [Theory] [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public async ValueTask FirstAsync_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) + public async Task FirstAsync_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .First(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .FirstAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Match( @@ -223,10 +233,11 @@ public async void FirstAsync_Predicate_Selector_With_Empty_Must_Return_None(int[ .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .FirstAsync(); + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -237,21 +248,22 @@ public async void FirstAsync_Predicate_Selector_With_Empty_Must_Return_None(int[ [Theory] [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public async ValueTask FirstAsync_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) + public async Task FirstAsync_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .First(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .FirstAsync(); + .FirstAsync() + .ConfigureAwait(false); // Assert _ = result.Match( @@ -259,4 +271,4 @@ public async ValueTask FirstAsync_Predicate_Selector_With_ValidData_Must_Return_ () => throw new Exception()); } } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ReadOnlyList.Tests.cs similarity index 73% rename from NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ReadOnlyMemory.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ReadOnlyList.Tests.cs index 978650f35..0350e1693 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ReadOnlyList.Tests.cs @@ -5,16 +5,18 @@ namespace NetFabric.Hyperlinq.UnitTests.Element.Single { - public class ReadOnlyMemoryTests + public class ReadOnlyListTests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] public void Single_With_Empty_Must_Return_None(int[] source) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Single(); // Assert @@ -28,11 +30,13 @@ public void Single_With_Empty_Must_Return_None(int[] source) public void Single_With_Single_Must_Return_Some(int[] source) { // Arrange - var expected = Enumerable - .Single(source); + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Single(); // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Single(); // Assert @@ -46,9 +50,11 @@ public void Single_With_Single_Must_Return_Some(int[] source) public void Single_With_Multiple_Must_Return_None(int[] source) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Single(); // Assert @@ -62,10 +68,12 @@ public void Single_With_Multiple_Must_Return_None(int[] source) public void Single_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Single(); // Assert @@ -79,12 +87,14 @@ public void Single_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange - var expected = - Enumerable.Single(source, predicate); + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Single(predicate); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Single(); // Assert @@ -98,10 +108,12 @@ public void Single_Predicate_With_Single_Must_Return_Some(int[] source, Func predicate) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Single(); // Assert @@ -115,10 +127,12 @@ public void Single_Predicate_With_Multiple_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Single(); // Assert @@ -132,13 +146,15 @@ public void Single_PredicateAt_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Where(predicate) .Single(); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Single(); // Assert @@ -152,10 +168,12 @@ public void Single_PredicateAt_With_Single_Must_Return_Some(int[] source, Func predicate) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Single(); // Assert @@ -169,10 +187,12 @@ public void Single_PredicateAt_With_Multiple_Must_Return_None(int[] source, Func public void Single_Selector_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -186,13 +206,14 @@ public void Single_Selector_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); var expected = - Enumerable.Single( - Enumerable.Select(source, selector)); + source.Select(selector).Single(); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -206,10 +227,12 @@ public void Single_Selector_With_Single_Must_Return_Some(int[] source, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -223,10 +246,12 @@ public void Single_Selector_With_Multiple_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -240,13 +265,15 @@ public void Single_SelectorAt_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Select(selector) .Single(); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -260,10 +287,12 @@ public void Single_SelectorAt_With_Single_Must_Return_Some(int[] source, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -277,10 +306,12 @@ public void Single_SelectorAt_With_Multiple_Must_Return_None(int[] source, Func< public void Single_Predicate_Selector_With_Empty_Must_Return_None(int[] source, Func predicate, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector) .Single(); @@ -295,14 +326,16 @@ public void Single_Predicate_Selector_With_Empty_Must_Return_None(int[] source, public void Single_Predicate_Selector_With_Single_Must_Return_Some(int[] source, Func predicate, Func selector) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = Wrap + .AsValueList(source); + var expected = source + .Where(predicate) .Select(selector) .Single(); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector) .Single(); @@ -317,10 +350,12 @@ public void Single_Predicate_Selector_With_Single_Must_Return_Some(int[] source, public void Single_Predicate_Selector_With_Multiple_Must_Return_None(int[] source, Func predicate, Func selector) { // Arrange + var wrapped = Wrap + .AsValueList(source); // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector) .Single(); diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.Memory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ReadOnlySpan.Tests.cs similarity index 75% rename from NetFabric.Hyperlinq.UnitTests/Element/Single/Single.Memory.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ReadOnlySpan.Tests.cs index 5c62f071f..34414f590 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.Memory.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ReadOnlySpan.Tests.cs @@ -5,16 +5,17 @@ namespace NetFabric.Hyperlinq.UnitTests.Element.Single { - public class MemoryTests + public class ReadOnlySpanTests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] public void Single_With_Empty_Must_Return_None(int[] source) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Single(); // Assert @@ -28,16 +29,17 @@ public void Single_With_Empty_Must_Return_None(int[] source) public void Single_With_Single_Must_Return_Some(int[] source) { // Arrange - var expected = Enumerable - .Single(source); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Single(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Single(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -46,9 +48,10 @@ public void Single_With_Single_Must_Return_Some(int[] source) public void Single_With_Multiple_Must_Return_None(int[] source) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Single(); // Assert @@ -62,9 +65,10 @@ public void Single_With_Multiple_Must_Return_None(int[] source) public void Single_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Single(); @@ -79,17 +83,18 @@ public void Single_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange - var expected = - Enumerable.Single(source, predicate); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Single(predicate); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Single(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -98,9 +103,10 @@ public void Single_Predicate_With_Single_Must_Return_Some(int[] source, Func predicate) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Single(); @@ -115,9 +121,10 @@ public void Single_Predicate_With_Multiple_Must_Return_None(int[] source, Func predicate) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Single(); @@ -132,18 +139,19 @@ public void Single_PredicateAt_With_Empty_Must_Return_None(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .Single(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Single(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -152,9 +160,10 @@ public void Single_PredicateAt_With_Single_Must_Return_Some(int[] source, Func predicate) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Single(); @@ -169,9 +178,10 @@ public void Single_PredicateAt_With_Multiple_Must_Return_None(int[] source, Func public void Single_Selector_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .Single(); @@ -186,18 +196,18 @@ public void Single_Selector_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); var expected = - Enumerable.Single( - Enumerable.Select(source, selector)); + source.Select(selector).Single(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .Single(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -206,9 +216,10 @@ public void Single_Selector_With_Single_Must_Return_Some(int[] source, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .Single(); @@ -223,9 +234,10 @@ public void Single_Selector_With_Multiple_Must_Return_None(int[] source, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .Single(); @@ -240,18 +252,19 @@ public void Single_SelectorAt_With_Empty_Must_Return_None(int[] source, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .Single(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .Single(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -260,9 +273,10 @@ public void Single_SelectorAt_With_Single_Must_Return_Some(int[] source, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Select(selector) .Single(); @@ -277,9 +291,10 @@ public void Single_SelectorAt_With_Multiple_Must_Return_None(int[] source, Func< public void Single_Predicate_Selector_With_Empty_Must_Return_None(int[] source, Func predicate, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .Single(); @@ -295,20 +310,21 @@ public void Single_Predicate_Selector_With_Empty_Must_Return_None(int[] source, public void Single_Predicate_Selector_With_Single_Must_Return_Some(int[] source, Func predicate, Func selector) { // Arrange - var expected = Enumerable - .Where(source, predicate) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) .Select(selector) .Single(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .Single(); // Assert _ = result.Match( - value => value.Must().BeEqualTo(expected), + value => value.Must().BeEqualTo(expected), () => throw new Exception()); } @@ -317,9 +333,10 @@ public void Single_Predicate_Selector_With_Single_Must_Return_Some(int[] source, public void Single_Predicate_Selector_With_Multiple_Must_Return_None(int[] source, Func predicate, Func selector) { // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Where(predicate) .Select(selector) .Single(); diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ValueEnumerable.Tests.cs similarity index 83% rename from NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ValueEnumerable.Tests.cs index 44a7ed031..b87cc4cab 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ValueEnumerable.Tests.cs @@ -16,8 +16,8 @@ public void Single_With_Empty_Must_Return_None(int[] source) .AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Single, Wrap.Enumerator, int>(wrapped); + var result = wrapped + .Single, Wrap.Enumerator, int>(); // Assert _ = result.Must() @@ -32,12 +32,12 @@ public void Single_With_Single_Must_Return_Some(int[] source) // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Single(source); + var expected = source + .Single(); // Act - var result = ValueEnumerableExtensions - .Single, Wrap.Enumerator, int>(wrapped); + var result = wrapped + .Single, Wrap.Enumerator, int>(); // Assert _ = result.Match( @@ -54,8 +54,8 @@ public void Single_With_Multiple_Must_Return_None(int[] source) .AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Single, Wrap.Enumerator, int>(wrapped); + var result = wrapped + .Single, Wrap.Enumerator, int>(); // Assert _ = result.Must() @@ -72,8 +72,8 @@ public void Single_Predicate_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Single(); // Assert @@ -89,12 +89,12 @@ public void Single_Predicate_With_Single_Must_Return_Some(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Single(); // Assert @@ -112,8 +112,8 @@ public void Single_Predicate_With_Multiple_Must_Return_None(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Single(); // Assert @@ -131,8 +131,8 @@ public void Single_PredicateAt_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Single(); // Assert @@ -148,13 +148,13 @@ public void Single_PredicateAt_With_Single_Must_Return_Some(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Single(); // Assert @@ -172,8 +172,8 @@ public void Single_PredicateAt_With_Multiple_Must_Return_None(int[] source, Func .AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Single(); // Assert @@ -191,8 +191,8 @@ public void Single_Selector_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .Single(); // Assert @@ -208,13 +208,13 @@ public void Single_Selector_With_Single_Must_Return_Some(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .Single(); // Assert @@ -232,8 +232,8 @@ public void Single_Selector_With_Multiple_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .Single(); // Assert @@ -251,8 +251,8 @@ public void Single_SelectorAt_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .Single(); // Assert @@ -268,13 +268,13 @@ public void Single_SelectorAt_With_Single_Must_Return_Some(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .Single(); // Assert @@ -292,8 +292,8 @@ public void Single_SelectorAt_With_Multiple_Must_Return_None(int[] source, Func< .AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector) .Single(); // Assert @@ -311,8 +311,8 @@ public void Single_Predicate_Selector_With_Empty_Must_Return_None(int[] source, .AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .Single(); @@ -329,14 +329,14 @@ public void Single_Predicate_Selector_With_Single_Must_Return_Some(int[] source, // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .Single(); // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .Single(); @@ -355,8 +355,8 @@ public void Single_Predicate_Selector_With_Multiple_Must_Return_None(int[] sourc .AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) .Select(selector) .Single(); diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ValueReadOnlyCollection.Tests.cs similarity index 73% rename from NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ValueReadOnlyCollection.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ValueReadOnlyCollection.Tests.cs index 25f7f34a5..c775732fd 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/Single.ValueReadOnlyCollection.Tests.cs @@ -16,8 +16,8 @@ public void Single_With_Empty_Must_Return_None(int[] source) .AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .Single, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .Single(); // Assert _ = result.Must() @@ -32,12 +32,12 @@ public void Single_With_Single_Must_Return_Some(int[] source) // Arrange var wrapped = Wrap .AsValueReadOnlyCollection(source); - var expected = Enumerable - .Single(source); + var expected = source + .Single(); // Act - var result = ValueReadOnlyCollectionExtensions - .Single, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .Single(); // Assert _ = result.Match( @@ -54,8 +54,8 @@ public void Single_With_Multiple_Must_Return_None(int[] source) .AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .Single, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .Single(); // Assert _ = result.Must() @@ -72,8 +72,8 @@ public void Single_Selector_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -89,13 +89,13 @@ public void Single_Selector_With_Single_Must_Return_Some(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -113,8 +113,8 @@ public void Single_Selector_With_Multiple_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -132,8 +132,8 @@ public void Single_SelectorAt_With_Empty_Must_Return_None(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -149,13 +149,13 @@ public void Single_SelectorAt_With_Single_Must_Return_Some(int[] source, Func, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert @@ -173,8 +173,8 @@ public void Single_SelectorAt_With_Multiple_Must_Return_None(int[] source, Func< .AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector) + var result = wrapped.AsValueEnumerable() + .Select(selector) .Single(); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/SingleAsync.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/SingleAsync.AsyncValueEnumerable.Tests.cs similarity index 59% rename from NetFabric.Hyperlinq.UnitTests/Element/Single/SingleAsync.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Element/Single/SingleAsync.AsyncValueEnumerable.Tests.cs index 38dd6d0a7..060688d0c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/SingleAsync.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Element/Single/SingleAsync.AsyncValueEnumerable.Tests.cs @@ -17,8 +17,9 @@ public async void SingleAsync_With_Empty_Must_Return_None(int[] source) .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .SingleAsync, Wrap.AsyncEnumerator, int>(wrapped); + var result = await wrapped.AsAsyncValueEnumerable() + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -28,22 +29,23 @@ public async void SingleAsync_With_Empty_Must_Return_None(int[] source) [Theory] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - public async ValueTask SingleAsync_With_SingleAsync_Must_Return_Some(int[] source) + public async Task SingleAsync_With_Single_Must_Return_Some(int[] source) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Single(source); + var expected = source + .Single(); // Act - var result = await AsyncValueEnumerableExtensions - .SingleAsync, Wrap.AsyncEnumerator, int>(wrapped); + var result = await wrapped.AsAsyncValueEnumerable() + .SingleAsync() + .ConfigureAwait(false); // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsSome && option.Value == expected); } [Theory] @@ -55,8 +57,9 @@ public async void SingleAsync_With_Multiple_Must_Return_None(int[] source) .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .SingleAsync, Wrap.AsyncEnumerator, int>(wrapped); + var result = await wrapped.AsAsyncValueEnumerable() + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -73,9 +76,10 @@ public async void SingleAsync_Predicate_With_Empty_Must_Return_None(int[] source .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -85,23 +89,24 @@ public async void SingleAsync_Predicate_With_Empty_Must_Return_None(int[] source [Theory] [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - public async ValueTask SingleAsync_Predicate_With_SingleAsync_Must_Return_Some(int[] source, Func predicate) + public async Task SingleAsync_Predicate_With_SingleAsync_Must_Return_Some(int[] source, Func predicate) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Single(source, predicate); + var expected = source + .Single(predicate); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsSome && option.Value == expected); } [Theory] @@ -113,9 +118,10 @@ public async void SingleAsync_Predicate_With_Multiple_Must_Return_None(int[] sou .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -132,9 +138,10 @@ public async void SingleAsync_PredicateAt_With_Empty_Must_Return_None(int[] sour .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -144,7 +151,7 @@ public async void SingleAsync_PredicateAt_With_Empty_Must_Return_None(int[] sour [Theory] [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - public async ValueTask SingleAsync_PredicateAt_With_SingleAsync_Must_Return_Some(int[] source, Func predicate) + public async Task SingleAsync_PredicateAt_With_SingleAsync_Must_Return_Some(int[] source, Func predicate) { // Arrange var wrapped = Wrap @@ -154,14 +161,15 @@ public async ValueTask SingleAsync_PredicateAt_With_SingleAsync_Must_Return_Some .Single(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsSome && option.Value == expected); } [Theory] @@ -173,9 +181,10 @@ public async void SingleAsync_PredicateAt_With_Multiple_Must_Return_None(int[] s .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -192,9 +201,10 @@ public async void SingleAsync_Selector_With_Empty_Must_Return_None(int[] source, .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -204,7 +214,7 @@ public async void SingleAsync_Selector_With_Empty_Must_Return_None(int[] source, [Theory] [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - public async ValueTask SingleAsync_Selector_With_SingleAsync_Must_Return_Some(int[] source, Func selector) + public async Task SingleAsync_Selector_With_SingleAsync_Must_Return_Some(int[] source, Func selector) { // Arrange var wrapped = Wrap @@ -214,14 +224,15 @@ public async ValueTask SingleAsync_Selector_With_SingleAsync_Must_Return_Some(in .Single(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsSome && option.Value == expected); } [Theory] @@ -233,9 +244,10 @@ public async void SingleAsync_Selector_With_Multiple_Must_Return_None(int[] sour .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -252,9 +264,10 @@ public async void SingleAsync_SelectorAt_With_Empty_Must_Return_None(int[] sourc .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -264,24 +277,25 @@ public async void SingleAsync_SelectorAt_With_Empty_Must_Return_None(int[] sourc [Theory] [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - public async ValueTask SingleAsync_SelectorAt_With_SingleAsync_Must_Return_Some(int[] source, Func selector) + public async Task SingleAsync_SelectorAt_With_SingleAsync_Must_Return_Some(int[] source, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Select(source, selector) + var expected = source + .Select(selector) .Single(); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsSome && option.Value == expected); } [Theory] @@ -293,9 +307,10 @@ public async void SingleAsync_SelectorAt_With_Multiple_Must_Return_None(int[] so .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()) - .SingleAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Select(selector.AsAsync()) + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -312,10 +327,11 @@ public async void SingleAsync_Predicate_Selector_With_Empty_Must_Return_None(int .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .SingleAsync(); + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -325,26 +341,27 @@ public async void SingleAsync_Predicate_Selector_With_Empty_Must_Return_None(int [Theory] [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - public async ValueTask SingleAsync_Predicate_Selector_With_SingleAsync_Must_Return_Some(int[] source, Func predicate, Func selector) + public async Task SingleAsync_Predicate_Selector_With_SingleAsync_Must_Return_Some(int[] source, Func predicate, Func selector) { // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate) + var expected = source + .Where(predicate) .Select(selector) .Single(); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .SingleAsync(); + .SingleAsync() + .ConfigureAwait(false); // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsSome && option.Value == expected); } [Theory] @@ -356,10 +373,11 @@ public async void SingleAsync_Predicate_Selector_With_Multiple_Must_Return_None( .AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) .Select(selector.AsAsync()) - .SingleAsync(); + .SingleAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -367,4 +385,4 @@ public async void SingleAsync_Predicate_Selector_With_Multiple_Must_Return_None( .EvaluateTrue(option => option.IsNone); } } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs similarity index 62% rename from NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs index 6a3f7dc4e..e9d142ba7 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs @@ -15,8 +15,8 @@ public void Where_With_NullArray_Must_Succeed() var expected = Enumerable.Empty(); // Act - var result = ArrayExtensions - .Where(source, _ => true); + var result = source.AsValueEnumerable() + .Where(_ => true); // Assert _ = result.Must() @@ -34,18 +34,18 @@ public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, // Arrange var (offset, count) = Utils.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate); + var expected = wrapped + .Where(predicate); // Act - var result = ArrayExtensions - .Where(wrapped, predicate); + var result = wrapped.AsValueEnumerable() + .Where(predicate); // Assert _ = result.Must() .BeEnumerableOf() .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + _ = Enumerable.SequenceEqual(result, expected).Must().BeTrue(); } [Theory] @@ -57,13 +57,13 @@ public void Where_Where_With_ValidData_Must_Succeed(int[] source, int skip, int // Arrange var (offset, count) = Utils.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate0) + var expected = wrapped + .Where(predicate0) .Where(predicate1); // Act - var result = ArrayExtensions - .Where(wrapped, predicate0) + var result = wrapped.AsValueEnumerable() + .Where(predicate0) .Where(predicate1); // Assert @@ -72,5 +72,28 @@ public void Where_Where_With_ValidData_Must_Succeed(int[] source, int skip, int .BeEqualTo(expected, testRefStructs: false); _ = result.SequenceEqual(expected).Must().BeTrue(); } + + [Theory] + [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] + public void Where_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) + { + // Arrange + var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var wrapped = new ArraySegment(source, offset, count); + var expected = wrapped + .Where(predicate) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.AsyncValueEnumerable.Tests.cs new file mode 100644 index 000000000..b6c21f4e4 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.AsyncValueEnumerable.Tests.cs @@ -0,0 +1,57 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where +{ + public class AsyncValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsAsyncValueEnumerable(source); + var expected = source + .Where(predicate); + + // Act + var result = wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()); + + // Assert + _ = result.Must() + .BeAsyncEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public async Task Where_Sum_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsAsyncValueEnumerable(source); + var expected = source + .Where(predicate) + .Sum(); + + // Act + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs new file mode 100644 index 000000000..8ac2bf608 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs @@ -0,0 +1,54 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where +{ + public class ReadOnlyMemoryTests + { + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Where(predicate); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); + _ = result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void Where_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Where(predicate) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ReadOnlySpan.Tests.cs similarity index 76% rename from NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlySpan.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ReadOnlySpan.Tests.cs index 27cd440f0..79edcd106 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlySpan.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ReadOnlySpan.Tests.cs @@ -14,12 +14,13 @@ public class ReadOnlySpanTests public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate); // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate); + var result = wrapped.AsValueEnumerable() + .Where(predicate); // Assert _ = result.SequenceEqual(expected).Must().BeTrue(); diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ValueEnumerable.Tests.cs new file mode 100644 index 000000000..f0049e1bc --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ValueEnumerable.Tests.cs @@ -0,0 +1,55 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where +{ + public class ValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsValueEnumerable(source); + var expected = source + .Where(predicate); + + // Act + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void Where_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsValueEnumerable(source); + var expected = source + .Where(predicate) + .Sum(); + + // Act + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..40d4d694f --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/Where/Where.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,55 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where +{ + public class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Where(predicate); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void Where_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Where(predicate) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs similarity index 58% rename from NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs index 738b3c16e..405191291 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs @@ -15,8 +15,8 @@ public void Where_With_NullArray_Must_Succeed() var expected = Enumerable.Empty(); // Act - var result = ArrayExtensions - .Where(source, (_, __) => true); + var result = source.AsValueEnumerable() + .Where((_, __) => true); // Assert _ = result.Must() @@ -38,8 +38,8 @@ public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, .Where(wrapped, predicate); // Act - var result = ArrayExtensions - .Where(wrapped, predicate); + var result = wrapped.AsValueEnumerable() + .Where(predicate); // Assert _ = result.Must() @@ -47,5 +47,28 @@ public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); _ = result.SequenceEqual(expected).Must().BeTrue(); } + + [Theory] + [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] + public void Where_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) + { + // Arrange + var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var wrapped = new ArraySegment(source, offset, count); + var expected = Enumerable + .Where(wrapped, predicate) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.AsyncValueEnumerable.Tests.cs new file mode 100644 index 000000000..3ac5990bf --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.AsyncValueEnumerable.Tests.cs @@ -0,0 +1,57 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereAt +{ + public class AsyncValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] + public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsAsyncValueEnumerable(source); + var expected = source + .Where(predicate); + + // Act + var result = wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()); + + // Assert + _ = result.Must() + .BeAsyncEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] + public async Task Where_Sum_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsAsyncValueEnumerable(source); + var expected = source + .Where(predicate) + .Sum(); + + // Act + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs new file mode 100644 index 000000000..1c4ccbb49 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs @@ -0,0 +1,54 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereIndex +{ + public class ReadOnlyMemoryTests + { + [Theory] + [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] + public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Where(predicate); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); + _ = result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] + public void Where_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Where(predicate) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlySpan.Tests.cs similarity index 76% rename from NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlySpan.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlySpan.Tests.cs index a981f0bf8..f6dcaad0f 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlySpan.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlySpan.Tests.cs @@ -14,12 +14,13 @@ public class ReadOnlySpanTests public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate); // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate); + var result = wrapped.AsValueEnumerable() + .Where(predicate); // Assert _ = result.SequenceEqual(expected).Must().BeTrue(); diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ValueEnumerable.Tests.cs new file mode 100644 index 000000000..aa293157f --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ValueEnumerable.Tests.cs @@ -0,0 +1,55 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereAt +{ + public class ValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] + public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsValueEnumerable(source); + var expected = source + .Where(predicate); + + // Act + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] + public void Where_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsValueEnumerable(source); + var expected = source + .Where(predicate) + .Sum(); + + // Act + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..15a5a77ce --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereAt/WhereAt.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,55 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereAt +{ + public class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] + public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Where(predicate); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] + public void Where_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Where(predicate) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs similarity index 55% rename from NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs index 0815d4163..da4512a1c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs @@ -8,15 +8,15 @@ namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect public class ArraySegmentTests { [Fact] - public void WhereRef_With_NullArray_Must_Succeed() + public void WhereSelect_With_NullArray_Must_Succeed() { // Arrange var source = default(ArraySegment); var expected = Enumerable.Empty(); // Act - var result = ArrayExtensions - .Where(source, _ => true) + var result = source.AsValueEnumerable() + .Where(_ => true) .Select(item => item.ToString()); // Assert @@ -35,20 +35,45 @@ public void WhereSelect_With_ValidData_Must_Succeed(int[] source, int skip, int // Arrange var (offset, count) = Utils.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate) + var expected = wrapped + .Where(predicate) .Select(selector); // Act - var result = ArrayExtensions - .Where(wrapped, predicate) + var result = wrapped.AsValueEnumerable() + .Where(predicate) .Select(selector); // Assert _ = result.Must() .BeEnumerableOf() .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + _ = Enumerable.SequenceEqual(result, expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] + public void WhereSelect_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) + { + // Arrange + var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var wrapped = new ArraySegment(source, offset, count); + var expected = Enumerable + .Where(wrapped, predicate) + .Select(item => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Select(item => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.AsyncValueEnumerable.Tests.cs new file mode 100644 index 000000000..859a55079 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.AsyncValueEnumerable.Tests.cs @@ -0,0 +1,59 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect +{ + public class AsyncValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] + public void WhereSelect_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Where(predicate) + .Select(selector); + + // Act + var result = wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .Select(selector.AsAsync()); + + // Assert + _ = result.Must() + .BeAsyncEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public async Task WhereSelect_Sum_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Where(predicate) + .Select(item => item) + .Sum(); + + // Act + var result = await wrapped.AsAsyncValueEnumerable() + .Where(predicate.AsAsync()) + .Select((item, _) => new ValueTask(item)) + .SumAsync() +.ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs new file mode 100644 index 000000000..52e2035c5 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs @@ -0,0 +1,58 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect +{ + public class ReadOnlyMemoryTests + { + [Theory] + [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] + public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Where(predicate) + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Select(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + _ = result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void WhereSelect_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Where(predicate) + .Select(item => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Select(item => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlySpan.Tests.cs new file mode 100644 index 000000000..bb6c336a0 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlySpan.Tests.cs @@ -0,0 +1,55 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect +{ + public class ReadOnlySpanTests + { + [Theory] + [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] + public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Select(selector); + + // Assert + _ = result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void WhereSelect_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate) + .Select(item => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Select(item => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ValueEnumerable.Tests.cs new file mode 100644 index 000000000..a1b1f39f7 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ValueEnumerable.Tests.cs @@ -0,0 +1,57 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect +{ + public class ValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] + public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Where(predicate) + .Select(selector); + + // Act + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) + .Select(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void WhereSelect_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Where(predicate) + .Select(item => item) + .Count(); + + // Act + var result = wrapped + .Where, Wrap.Enumerator, int>(predicate) + .Select(item => item) + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..7a946af1f --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Filtering/WhereSelect/WhereSelect.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,57 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect +{ + public class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] + public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Where(predicate) + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Select(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void WhereSelect_Sum_With_ValidData_Must_Succeed(int[] source, Func predicate) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Where(predicate) + .Select(item => item) + .Count(); + + // Act + var result = wrapped.AsValueEnumerable() + .Where(predicate) + .Select(item => item) + .Count(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Empty.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Empty.Tests.cs similarity index 100% rename from NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Empty.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Empty.Tests.cs diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Range.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Range.Tests.cs similarity index 80% rename from NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Range.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Range.Tests.cs index abca4cf1b..2b4dde9bc 100644 --- a/NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Range.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Range.Tests.cs @@ -74,13 +74,15 @@ public void Range_Take_With_ValidData_Must_Succeed(int start, int count, int tak [Theory] [MemberData(nameof(TestData.Range), MemberType = typeof(TestData))] - public async ValueTask Range_AnyAsync_With_ValidData_Must_Succeed(int start, int count) + public async Task Range_AnyAsync_With_ValidData_Must_Succeed(int start, int count) { // Arrange var expected = Enumerable.Any(Enumerable.Range(start, count)); // Act - var result = await AsyncValueEnumerable.Range(start, count).AnyAsync(); + var result = await AsyncValueEnumerable.Range(start, count) + .AnyAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -89,13 +91,16 @@ public async ValueTask Range_AnyAsync_With_ValidData_Must_Succeed(int start, int [Theory] [MemberData(nameof(TestData.Range_Contains), MemberType = typeof(TestData))] - public async ValueTask Range_ContainsAsync_With_ValidData_Must_Succeed(int start, int count, int value) + public async Task Range_ContainsAsync_With_ValidData_Must_Succeed(int start, int count, int value) { // Arrange var expected = Enumerable.Contains(Enumerable.Range(start, count), value); // Act - var result = await AsyncValueEnumerable.Range(start, count).ContainsAsync(value); + var result = await AsyncValueEnumerable + .Range(start, count) + .ContainsAsync(value) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -104,13 +109,16 @@ public async ValueTask Range_ContainsAsync_With_ValidData_Must_Succeed(int start [Theory] [MemberData(nameof(TestData.Range), MemberType = typeof(TestData))] - public async ValueTask Range_ToArray_With_ValidData_Must_Succeed(int start, int count) + public async Task Range_ToArray_With_ValidData_Must_Succeed(int start, int count) { // Arrange var expected = Enumerable.ToArray(Enumerable.Range(start, count)); // Act - var result = await AsyncValueEnumerable.Range(start, count).ToArrayAsync(); + var result = await AsyncValueEnumerable + .Range(start, count) + .ToArrayAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -120,13 +128,16 @@ public async ValueTask Range_ToArray_With_ValidData_Must_Succeed(int start, int [Theory] [MemberData(nameof(TestData.Range), MemberType = typeof(TestData))] - public async ValueTask Range_With_ToList_Must_Succeed(int start, int count) + public async Task Range_With_ToList_Must_Succeed(int start, int count) { // Arrange var expected = Enumerable.ToList(Enumerable.Range(start, count)); // Act - var result = await AsyncValueEnumerable.Range(start, count).ToListAsync(); + var result = await AsyncValueEnumerable + .Range(start, count) + .ToListAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -135,4 +146,4 @@ public async ValueTask Range_With_ToList_Must_Succeed(int start, int count) .BeEqualTo(expected); } } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Repeat.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Repeat.Tests.cs similarity index 67% rename from NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Repeat.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Repeat.Tests.cs index 3a59d55a4..8353dacbf 100644 --- a/NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Repeat.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Repeat.Tests.cs @@ -46,7 +46,7 @@ public void Repeat_With_ValidData_Must_Succeed(int value, int count) public void Repeat_Skip_With_ValidData_Must_Succeed(int value, int count, int skip) { // Arrange - var expected = Enumerable.Skip(Enumerable.Repeat(value, count), skip); + var expected = Enumerable.Repeat(value, count).Skip(skip); // Act var result = AsyncValueEnumerable.Repeat(value, count).Skip(skip); @@ -62,7 +62,7 @@ public void Repeat_Skip_With_ValidData_Must_Succeed(int value, int count, int sk public void Repeat_Take_With_ValidData_Must_Succeed(int value, int count, int take) { // Arrange - var expected = Enumerable.Take(Enumerable.Repeat(value, count), take); + var expected = Enumerable.Repeat(value, count).Take(take); // Act var result = AsyncValueEnumerable.Repeat(value, count).Take(take); @@ -75,13 +75,16 @@ public void Repeat_Take_With_ValidData_Must_Succeed(int value, int count, int ta [Theory] [MemberData(nameof(TestData.Repeat), MemberType = typeof(TestData))] - public async ValueTask Repeat_All_With_ValidData_Must_Succeed(int value, int count) + public async Task Repeat_All_With_ValidData_Must_Succeed(int value, int count) { // Arrange - var expected = Enumerable.All(Enumerable.Repeat(value, count), item => false); + var expected = Enumerable.Repeat(value, count).All(item => false); // Act - var result = await AsyncValueEnumerable.Repeat(value, count).AllAsync(item => false); + var result = await AsyncValueEnumerable + .Repeat(value, count) + .AllAsync(item => false) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -90,13 +93,16 @@ public async ValueTask Repeat_All_With_ValidData_Must_Succeed(int value, int cou [Theory] [MemberData(nameof(TestData.Repeat), MemberType = typeof(TestData))] - public async ValueTask Repeat_Any_With_ValidData_Must_Succeed(int value, int count) + public async Task Repeat_Any_With_ValidData_Must_Succeed(int value, int count) { // Arrange - var expected = Enumerable.Any(Enumerable.Repeat(value, count)); + var expected = Enumerable.Repeat(value, count).Any(); // Act - var result = await AsyncValueEnumerable.Repeat(value, count).AnyAsync(); + var result = await AsyncValueEnumerable + .Repeat(value, count) + .AnyAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -105,13 +111,16 @@ public async ValueTask Repeat_Any_With_ValidData_Must_Succeed(int value, int cou [Theory] [MemberData(nameof(TestData.Repeat), MemberType = typeof(TestData))] - public async ValueTask Repeat_ToArray_With_ValidData_Must_Succeed(int value, int count) + public async Task Repeat_ToArray_With_ValidData_Must_Succeed(int value, int count) { // Arrange - var expected = Enumerable.ToArray(Enumerable.Repeat(value, count)); + var expected = Enumerable.Repeat(value, count).ToArray(); // Act - var result = await AsyncValueEnumerable.Repeat(value, count).ToArrayAsync(); + var result = await AsyncValueEnumerable + .Repeat(value, count) + .ToArrayAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -121,19 +130,20 @@ public async ValueTask Repeat_ToArray_With_ValidData_Must_Succeed(int value, int [Theory] [MemberData(nameof(TestData.Repeat), MemberType = typeof(TestData))] - public async ValueTask Repeat_ToList_With_ValidData_Must_Succeed(int value, int count) + public async Task Repeat_ToList_With_ValidData_Must_Succeed(int value, int count) { // Arrange - var expected = Enumerable.ToList(Enumerable.Repeat(value, count)); + var expected = Enumerable.Repeat(value, count).ToList(); // Act - var result = await AsyncValueEnumerable.Repeat(value, count).ToListAsync(); + var result = await AsyncValueEnumerable + .Repeat(value, count) + .ToListAsync() + .ConfigureAwait(false); // Assert _ = result.Must() - .BeOfType>() - .BeAsyncEnumerableOf() - .BeEqualTo(expected); + .EvaluateTrue(list => list.SequenceEqual(expected)); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Return.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Return.Tests.cs similarity index 100% rename from NetFabric.Hyperlinq.UnitTests/Generation/AsyncValueEnumerable/Return.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/AsyncValueEnumerable/Return.Tests.cs diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/Range.TestData.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/Range.TestData.cs similarity index 79% rename from NetFabric.Hyperlinq.UnitTests/Generation/Range.TestData.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/Range.TestData.cs index 43de5fd24..3eac0d4c7 100644 --- a/NetFabric.Hyperlinq.UnitTests/Generation/Range.TestData.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Generation/Range.TestData.cs @@ -6,7 +6,7 @@ namespace NetFabric.Hyperlinq public static partial class TestData { public static TheoryData Range => - new TheoryData + new() { { -1, 0 }, { 0, 0 }, @@ -14,21 +14,21 @@ public static partial class TestData { -1, 1 }, { -1, 20 }, - { 1, 20 }, + { 1, 20 } }; public static TheoryData Range_SkipTake => - new TheoryData + new() { { 1, 5, -1 }, { 1, 5, 0 }, { 1, 5, 1 }, { 1, 5, 2 }, - { 1, 5, 20 }, + { 1, 5, 20 } }; public static TheoryData Range_Contains => - new TheoryData + new() { { 0, 0, 0 }, { 1, 5, -1 }, @@ -36,7 +36,7 @@ public static partial class TestData { 1, 5, 1 }, { 1, 5, 4 }, { 1, 5, 5 }, - { 1, 5, 20 }, + { 1, 5, 20 } }; } } diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/Repeat.TestData.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/Repeat.TestData.cs similarity index 69% rename from NetFabric.Hyperlinq.UnitTests/Generation/Repeat.TestData.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/Repeat.TestData.cs index a6f5d31dc..2208d8cf8 100644 --- a/NetFabric.Hyperlinq.UnitTests/Generation/Repeat.TestData.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Generation/Repeat.TestData.cs @@ -6,16 +6,15 @@ namespace NetFabric.Hyperlinq public static partial class TestData { public static TheoryData Repeat => - new TheoryData + new() { - { 0, 0 }, - { 0, 1 }, - { 0, 5 }, - { 5, 5 }, + { 1, 0 }, + { 1, 1 }, + { 1, 5 }, }; public static TheoryData Repeat_SkipTake => - new TheoryData + new() { { 1, 0, 0 }, { 1, 5, -1 }, @@ -23,7 +22,7 @@ public static partial class TestData { 1, 5, 1 }, { 1, 5, 4 }, { 1, 5, 5 }, - { 1, 5, 10 }, + { 1, 5, 10 } }; } } diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/Return.TestData.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/Return.TestData.cs similarity index 72% rename from NetFabric.Hyperlinq.UnitTests/Generation/Return.TestData.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/Return.TestData.cs index 27f13098f..a7afa58f7 100644 --- a/NetFabric.Hyperlinq.UnitTests/Generation/Return.TestData.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Generation/Return.TestData.cs @@ -6,9 +6,9 @@ namespace NetFabric.Hyperlinq public static partial class TestData { public static TheoryData Return => - new TheoryData + new() { - int.MinValue, 0, int.MaxValue, + int.MinValue, 0, int.MaxValue }; } } diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Empty.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Empty.Tests.cs similarity index 100% rename from NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Empty.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Empty.Tests.cs diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Range.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Range.Tests.cs similarity index 79% rename from NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Range.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Range.Tests.cs index 0a769fdfa..b8961b596 100644 --- a/NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Range.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Range.Tests.cs @@ -44,7 +44,7 @@ public void Range_With_ValidData_Must_Succeed(int start, int count) public void Range_Skip_With_ValidData_Must_Succeed(int start, int count, int skip) { // Arrange - var expected = Enumerable.Skip(Enumerable.Range(start, count), skip); + var expected = Enumerable.Range(start, count).Skip(skip); // Act var result = ValueEnumerable.Range(start, count).Skip(skip); @@ -60,7 +60,7 @@ public void Range_Skip_With_ValidData_Must_Succeed(int start, int count, int ski public void Range_Take_With_ValidData_Must_Succeed(int start, int count, int take) { // Arrange - var expected = Enumerable.Take(Enumerable.Range(start, count), take); + var expected = Enumerable.Range(start, count).Take(take); // Act var result = ValueEnumerable.Range(start, count).Take(take); @@ -76,7 +76,7 @@ public void Range_Take_With_ValidData_Must_Succeed(int start, int count, int tak public void Range_Any_With_ValidData_Must_Succeed(int start, int count) { // Arrange - var expected = Enumerable.Any(Enumerable.Range(start, count)); + var expected = Enumerable.Range(start, count).Any(); // Act var result = ValueEnumerable.Range(start, count).Any(); @@ -91,7 +91,7 @@ public void Range_Any_With_ValidData_Must_Succeed(int start, int count) public void Range_Contains_With_ValidData_Must_Succeed(int start, int count, int value) { // Arrange - var expected = Enumerable.Contains(Enumerable.Range(start, count), value); + var expected = Enumerable.Range(start, count).Contains(value); // Act var result = ValueEnumerable.Range(start, count).Contains(value); @@ -106,7 +106,7 @@ public void Range_Contains_With_ValidData_Must_Succeed(int start, int count, int public void Range_ToArray_With_ValidData_Must_Succeed(int start, int count) { // Arrange - var expected = Enumerable.ToArray(Enumerable.Range(start, count)); + var expected = Enumerable.Range(start, count).ToArray(); // Act var result = ValueEnumerable.Range(start, count).ToArray(); @@ -122,7 +122,7 @@ public void Range_ToArray_With_ValidData_Must_Succeed(int start, int count) public void Range_With_ToList_Must_Succeed(int start, int count) { // Arrange - var expected = Enumerable.ToList(Enumerable.Range(start, count)); + var expected = Enumerable.Range(start, count).ToList(); // Act var result = ValueEnumerable.Range(start, count).ToList(); @@ -134,29 +134,13 @@ public void Range_With_ToList_Must_Succeed(int start, int count) .BeEqualTo(expected); } - [Theory] - [MemberData(nameof(TestData.Range), MemberType = typeof(TestData))] - public void Range_SelectVector_Must_Succeed(int start, int count) - { - // Arrange - var expected = Enumerable.Select(Enumerable.Range(start, count), item => item * 2); - - // Act - var result = ValueEnumerable.Range(start, count).SelectVector(item => item * 2, item => item * 2); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - [Theory] [MemberData(nameof(TestData.Range), MemberType = typeof(TestData))] public void Range_SelectVector_Sum_Must_Succeed(int start, int count) { // Arrange - var expected = Enumerable.Sum(Enumerable.Select(Enumerable.Range(start, count), item => item * 2)); + var expected = Enumerable.Range(start, count).Select(item => item * 2).Sum(); // Act var result = ValueEnumerable.Range(start, count).SelectVector(item => item * 2, item => item * 2).Sum(); @@ -172,7 +156,7 @@ public void Range_SelectVector_Sum_Must_Succeed(int start, int count) public void Range_SelectVector_ToArray_Must_Succeed(int start, int count) { // Arrange - var expected = Enumerable.ToArray(Enumerable.Select(Enumerable.Range(start, count), item => item * 2)); + var expected = Enumerable.Range(start, count).Select(item => item * 2).ToArray(); // Act var result = ValueEnumerable.Range(start, count).SelectVector(item => item * 2, item => item * 2).ToArray(); @@ -188,7 +172,7 @@ public void Range_SelectVector_ToArray_Must_Succeed(int start, int count) public void Range_SelectVector_ToList_Must_Succeed(int start, int count) { // Arrange - var expected = Enumerable.ToList(Enumerable.Select(Enumerable.Range(start, count), item => item * 2)); + var expected = Enumerable.Range(start, count).Select(item => item * 2).ToList(); // Act var result = ValueEnumerable.Range(start, count).SelectVector(item => item * 2, item => item * 2).ToList(); diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Repeat.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Repeat.Tests.cs similarity index 71% rename from NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Repeat.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Repeat.Tests.cs index a57516052..a5aad7217 100644 --- a/NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Repeat.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Repeat.Tests.cs @@ -1,6 +1,7 @@ using NetFabric.Assertive; using System; using System.Collections.Generic; +using System.Linq; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Generation.ValueEnumerableTests @@ -28,7 +29,7 @@ public void Repeat_With_NegativeCount_Must_Throw(int count) public void Repeat_With_ValidData_Must_Succeed(int value, int count) { // Arrange - var expected = System.Linq.Enumerable.Repeat(value, count); + var expected = Enumerable.Repeat(value, count); // Act var result = ValueEnumerable.Repeat(value, count); @@ -44,10 +45,14 @@ public void Repeat_With_ValidData_Must_Succeed(int value, int count) public void Repeat_Skip_With_ValidData_Must_Succeed(int value, int count, int skip) { // Arrange - var expected = System.Linq.Enumerable.Skip(System.Linq.Enumerable.Repeat(value, count), skip); + var expected = Enumerable + .Repeat(value, count) + .Skip(skip); // Act - var result = ValueEnumerable.Repeat(value, count).Skip(skip); + var result = ValueEnumerable + .Repeat(value, count) + .Skip(skip); // Assert _ = result.Must() @@ -60,10 +65,14 @@ public void Repeat_Skip_With_ValidData_Must_Succeed(int value, int count, int sk public void Repeat_Take_With_ValidData_Must_Succeed(int value, int count, int take) { // Arrange - var expected = System.Linq.Enumerable.Take(System.Linq.Enumerable.Repeat(value, count), take); + var expected = Enumerable + .Repeat(value, count) + .Take(take); // Act - var result = ValueEnumerable.Repeat(value, count).Take(take); + var result = ValueEnumerable + .Repeat(value, count) + .Take(take); // Assert _ = result.Must() @@ -76,10 +85,14 @@ public void Repeat_Take_With_ValidData_Must_Succeed(int value, int count, int ta public void Repeat_All_With_ValidData_Must_Succeed(int value, int count) { // Arrange - var expected = System.Linq.Enumerable.All(System.Linq.Enumerable.Repeat(value, count), item => false); + var expected = Enumerable + .Repeat(value, count) + .All(item => false); // Act - var result = ValueEnumerable.Repeat(value, count).All(item => false); + var result = ValueEnumerable + .Repeat(value, count) + .All(item => false); // Assert _ = result.Must() @@ -91,10 +104,14 @@ public void Repeat_All_With_ValidData_Must_Succeed(int value, int count) public void Repeat_Any_With_ValidData_Must_Succeed(int value, int count) { // Arrange - var expected = System.Linq.Enumerable.Any(System.Linq.Enumerable.Repeat(value, count)); + var expected = Enumerable + .Repeat(value, count) + .Any(); // Act - var result = ValueEnumerable.Repeat(value, count).Any(); + var result = ValueEnumerable + .Repeat(value, count) + .Any(); // Assert _ = result.Must() @@ -106,10 +123,14 @@ public void Repeat_Any_With_ValidData_Must_Succeed(int value, int count) public void Repeat_ToArray_With_ValidData_Must_Succeed(int value, int count) { // Arrange - var expected = System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Repeat(value, count)); + var expected = Enumerable + .Repeat(value, count) + .ToArray(); // Act - var result = ValueEnumerable.Repeat(value, count).ToArray(); + var result = ValueEnumerable + .Repeat(value, count) + .ToArray(); // Assert _ = result.Must() @@ -122,10 +143,14 @@ public void Repeat_ToArray_With_ValidData_Must_Succeed(int value, int count) public void Repeat_ToList_With_ValidData_Must_Succeed(int value, int count) { // Arrange - var expected = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Repeat(value, count)); + var expected = Enumerable + .Repeat(value, count) + .ToList(); // Act - var result = ValueEnumerable.Repeat(value, count).ToList(); + var result = ValueEnumerable + .Repeat(value, count) + .ToList(); // Assert _ = result.Must() diff --git a/NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Return.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Return.Tests.cs similarity index 93% rename from NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Return.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Return.Tests.cs index a9d1dd025..6f4f2870f 100644 --- a/NetFabric.Hyperlinq.UnitTests/Generation/ValueEnumerable/Return.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Generation/ValueEnumerable/Return.Tests.cs @@ -33,7 +33,7 @@ public void Indexer_With_IndexOutOfRange_Must_Throw(int value, int index) Func action = () => ValueEnumerable.Return(value)[index]; // Assert - _ = action.Must().Throw(); + _ = action.Must().Throw(); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/GlobalSuppressions.cs b/NetFabric.Hyperlinq.Core.UnitTests/GlobalSuppressions.cs similarity index 100% rename from NetFabric.Hyperlinq.UnitTests/GlobalSuppressions.cs rename to NetFabric.Hyperlinq.Core.UnitTests/GlobalSuppressions.cs diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/NetFabric.Hyperlinq.SourceGenerator.UnitTests.csproj b/NetFabric.Hyperlinq.Core.UnitTests/NetFabric.Hyperlinq.Core.UnitTests.csproj similarity index 52% rename from NetFabric.Hyperlinq.SourceGenerator.UnitTests/NetFabric.Hyperlinq.SourceGenerator.UnitTests.csproj rename to NetFabric.Hyperlinq.Core.UnitTests/NetFabric.Hyperlinq.Core.UnitTests.csproj index 59b3eb9fe..d7c4ddcb2 100644 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/NetFabric.Hyperlinq.SourceGenerator.UnitTests.csproj +++ b/NetFabric.Hyperlinq.Core.UnitTests/NetFabric.Hyperlinq.Core.UnitTests.csproj @@ -1,35 +1,36 @@  - net5.0 - + net48;netcoreapp2.1;netcoreapp3.1;net6.0 false - enable - + - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers - + - - Always - + diff --git a/NetFabric.Hyperlinq.UnitTests/Option/Option.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Option/Option.Tests.cs similarity index 96% rename from NetFabric.Hyperlinq.UnitTests/Option/Option.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Option/Option.Tests.cs index 31139eea7..66560026c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Option/Option.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Option/Option.Tests.cs @@ -25,7 +25,7 @@ public void Option_With_None_Must_Succeed() [Theory] [MemberData(nameof(TestData.OptionSome), MemberType = typeof(TestData))] - public void Option_With_Some_Must_Succeed(string expected) + public void Option_With_Some_Must_Succeed(string? expected) { // Arrange var option = Option.Some(expected); @@ -59,7 +59,7 @@ public void Option_MatchFunc_With_None_Must_Call_None() [Theory] [MemberData(nameof(TestData.OptionSome), MemberType = typeof(TestData))] - public void Option_MatchFunc_With_Some_Must_Call_Some(string expected) + public void Option_MatchFunc_With_Some_Must_Call_Some(string? expected) { // Arrange var option = Option.Some(expected); @@ -91,7 +91,7 @@ public void Option_MatchAction_With_None_Must_Call_None() [Theory] [MemberData(nameof(TestData.OptionSome), MemberType = typeof(TestData))] - public void Option_MatchActionWith_Some_Must_Call_Some(string expected) + public void Option_MatchActionWith_Some_Must_Call_Some(string? expected) { // Arrange var option = Option.Some(expected); @@ -121,7 +121,7 @@ public void Option_Count_With_None_Must_Return_0() [Theory] [MemberData(nameof(TestData.OptionSome), MemberType = typeof(TestData))] - public void Option_Count_With_Some_Must_Return_1(string value) + public void Option_Count_With_Some_Must_Return_1(string? value) { // Arrange var option = Option.Some(value); @@ -148,7 +148,7 @@ public void Option_Any_With_None_Must_Return_False() [Theory] [MemberData(nameof(TestData.OptionSome), MemberType = typeof(TestData))] - public void Option_Any_With_Some_Must_Return_True(string value) + public void Option_Any_With_Some_Must_Return_True(string? value) { // Arrange var option = Option.Some(value); @@ -178,7 +178,7 @@ public void Option_SelectMany_With_None_Must_Succeed(int[] expected) [Theory] [MemberData(nameof(TestData.OptionSomeSelectMany), MemberType = typeof(TestData))] - public void Option_SelectMany_With_Some_Must_Succeed(string value, int[] expected) + public void Option_SelectMany_With_Some_Must_Succeed(string? value, int[] expected) { // Arrange var option = Option.Some(value); diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Option/TestData.Option.cs b/NetFabric.Hyperlinq.Core.UnitTests/Option/TestData.Option.cs new file mode 100644 index 000000000..ebc5c3512 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Option/TestData.Option.cs @@ -0,0 +1,41 @@ +using System; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + public static TheoryData OptionSome => + new() + { + default, + string.Empty, + "string" + }; + + public static TheoryData OptionNoneSelectMany => + new() + { + Array.Empty(), + new[] { 1 }, + new[] { 1, 2, 3, 4, 5 } + }; + + public static TheoryData OptionSomeSelectMany => + new() + { + { default, Array.Empty() }, + { default, new[] { 1 } }, + { default, new[] { 1, 2, 3, 4, 5 } }, + { string.Empty, Array.Empty() }, + { string.Empty, new[] { 1 } }, + { string.Empty, new[] { 1, 2, 3, 4, 5 } }, + { "string", Array.Empty() }, + { "string", new[] { 1 } }, + { "string", new[] { 1, 2, 3, 4, 5 } } + }; + + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip.TestData.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip.TestData.cs new file mode 100644 index 000000000..3d98477e4 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip.TestData.cs @@ -0,0 +1,34 @@ +using System; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + public static TheoryData Skip_Skip => + new() + { + { Array.Empty(), -1, -1 }, + { Array.Empty(), 0, -1 }, + { Array.Empty(), 1, -1 }, + + { Array.Empty(), -1, 0 }, + { Array.Empty(), 0, 0 }, + { Array.Empty(), 1, 0 }, + + { new[] { 1 }, -1, -1 }, + { new[] { 1 }, 0, 0 }, + { new[] { 1 }, 1, 1 }, + { new[] { 1 }, 5, 5 }, + + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, -1 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 0 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 2 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 5, 5 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 10 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 20, 20 } + }; + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.AsyncValueEnumerable.Tests.cs similarity index 73% rename from NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.AsyncValueEnumerable.Tests.cs index 0d2435c77..794992bee 100644 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.AsyncValueEnumerable.Tests.cs @@ -15,12 +15,12 @@ public void Skip_With_ValidData_Must_Succeed(int[] source, int count) // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Skip(source, count); + var expected = source + .Skip(count); // Act - var result = AsyncValueEnumerableExtensions - .Skip, Wrap.AsyncEnumerator, int>(wrapped, count); + var result = wrapped.AsAsyncValueEnumerable() + .Skip(count); // Assert _ = result.Must() @@ -35,13 +35,13 @@ public void Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Skip(source, count0) + var expected = source + .Skip(count0) .Skip(count1); // Act - var result = AsyncValueEnumerableExtensions - .Skip, Wrap.AsyncEnumerator, int>(wrapped, count0) + var result = wrapped.AsAsyncValueEnumerable() + .Skip(count0) .Skip(count1); // Assert @@ -59,13 +59,13 @@ public void Skip_Take_With_ValidData_Must_Succeed(int[] source, int skip, int ta // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take); // Act - var result = AsyncValueEnumerableExtensions - .Skip, Wrap.AsyncEnumerator, int>(wrapped, skip) + var result = wrapped.AsAsyncValueEnumerable() + .Skip(skip) .Take(take); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs similarity index 74% rename from NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs index 62f9019da..3bebb91c3 100644 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs @@ -15,12 +15,12 @@ public void Skip_With_ValidData_Must_Succeed(int[] source, int count) // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Skip(source, count); + var expected = source + .Skip(count); // Act - var result = ValueEnumerableExtensions - .Skip, Wrap.Enumerator, int>(wrapped, count); + var result = wrapped.AsValueEnumerable() + .Skip(count); // Assert _ = result.Must() @@ -35,13 +35,13 @@ public void Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Skip(source, count0) + var expected = source + .Skip(count0) .Skip( count1); // Act - var result = ValueEnumerableExtensions - .Skip, Wrap.Enumerator, int>(wrapped, count0) + var result = wrapped.AsValueEnumerable() + .Skip(count0) .Skip(count1); // Assert @@ -59,13 +59,13 @@ public void Skip_Take_With_ValidData_Must_Succeed(int[] source, int skip, int ta // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Skip(source, skip) + var expected = source + .Skip(skip) .Take(take); // Act - var result = ValueEnumerableExtensions - .Skip, Wrap.Enumerator, int>(wrapped, skip) + var result = wrapped.AsValueEnumerable() + .Skip(skip) .Take(take); // Assert diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..f1057fcf8 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,77 @@ +using NetFabric.Assertive; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip +{ + public class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] + public void Skip_With_ValidData_Must_Succeed(int[] source, int count) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Skip(count); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(count); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] + public void Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Skip(count0) + .Skip(count1); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(count0) + .Skip(count1); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void Skip_Take_With_ValidData_Must_Succeed(int[] source, int skip, int take) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Skip(skip) + .Take(take); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(skip) + .Take(take); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.ValueReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.ValueReadOnlyList.Tests.cs new file mode 100644 index 000000000..fd830e303 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Skip/Skip.ValueReadOnlyList.Tests.cs @@ -0,0 +1,77 @@ +using NetFabric.Assertive; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip +{ + public class ValueReadOnlyListTests + { + [Theory] + [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] + public void Skip_With_ValidData_Must_Succeed(int[] source, int count) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Skip(count); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(count); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] + public void Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Skip(count0) + .Skip(count1); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(count0) + .Skip(count1); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void Skip_Take_With_ValidData_Must_Succeed(int[] source, int skip, int take) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Skip(skip) + .Take(take); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(skip) + .Take(take); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/SkipTake.TestData.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/SkipTake.TestData.cs new file mode 100644 index 000000000..41eb95d4f --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/SkipTake.TestData.cs @@ -0,0 +1,27 @@ +using System; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + public static TheoryData SkipTake_Take => + new() + { + { Array.Empty(), 0, 0, -1 }, + { Array.Empty(), 0, 0, 0 }, + { Array.Empty(), 0, 0, 1 }, + + { new[] { 1 }, 0, 1, -1 }, + { new[] { 1 }, 0, 1, 0 }, + { new[] { 1 }, 0, 1, 1 }, + { new[] { 1 }, 0, 1, 5 }, + + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 2, -1 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 2, 0 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 2, 5 } + }; + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take.TestData.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take.TestData.cs new file mode 100644 index 000000000..4fdd4d97b --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take.TestData.cs @@ -0,0 +1,41 @@ +using System; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + public static TheoryData Take_Take => + new() + { + { Array.Empty(), -1, -1 }, + { Array.Empty(), 0, -1 }, + { Array.Empty(), 1, -1 }, + + { Array.Empty(), -1, 0 }, + { Array.Empty(), 0, 0 }, + { Array.Empty(), 1, 0 }, + { Array.Empty(), 0, 1 }, + + { new[] { 1 }, -1, -1 }, + { new[] { 1 }, 0, 0 }, + { new[] { 1 }, 0, 1 }, + { new[] { 1 }, 1, 0 }, + { new[] { 1 }, 1, 1 }, + { new[] { 1 }, 5, 2 }, + { new[] { 1 }, 5, 5 }, + + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, -1 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 4, 0 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 4, 1 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 1, 4 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 4, 2 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 10 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 20, 20 } + }; + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.AsyncValueEnumerable.Tests.cs similarity index 53% rename from NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.AsyncValueEnumerable.Tests.cs index 2b36c02ac..872fea42b 100644 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.AsyncValueEnumerable.Tests.cs @@ -15,12 +15,12 @@ public void Take_With_ValidData_Must_Succeed(int[] source, int count) // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Take(source, count); + var expected = source + .Take(count); // Act - var result = AsyncValueEnumerableExtensions - .Take, Wrap.AsyncEnumerator, int>(wrapped, count); + var result = wrapped.AsAsyncValueEnumerable() + .Take(count); // Assert _ = result.Must() @@ -35,13 +35,13 @@ public void Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int // Arrange var wrapped = Wrap .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Take(source, count0) + var expected = source + .Take(count0) .Take(count1); // Act - var result = AsyncValueEnumerableExtensions - .Take, Wrap.AsyncEnumerator, int>(wrapped, count0) + var result = wrapped.AsAsyncValueEnumerable() + .Take(count0) .Take(count1); // Assert @@ -49,5 +49,29 @@ public void Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int .BeAsyncEnumerableOf() .BeEqualTo(expected); } + + [Theory] + [MemberData(nameof(TestData.TakeSkipEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSkipSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSkipMultiple), MemberType = typeof(TestData))] + public void Take_Skip_With_ValidData_Must_Succeed(int[] source, int take, int skip) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Take(take) + .Skip(skip); + + // Act + var result = wrapped.AsValueEnumerable() + .Take(take) + .Skip(skip); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.ValueEnumerable.Tests.cs similarity index 53% rename from NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.ValueEnumerable.Tests.cs index a8dee9d58..af583f1b7 100644 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.ValueEnumerable.Tests.cs @@ -15,12 +15,12 @@ public void Take_With_ValidData_Must_Succeed(int[] source, int count) // Arrange var wrapped = Wrap .AsValueEnumerable(source); - var expected = Enumerable - .Take(wrapped, count); + var expected = source + .Take(count); // Act - var result = ValueEnumerableExtensions - .Take, Wrap.Enumerator, int>(wrapped, count); + var result = wrapped.AsValueEnumerable() + .Take(count); // Assert _ = result.Must() @@ -34,13 +34,13 @@ public void Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int { // Arrange var wrapped = Wrap.AsValueEnumerable(source); - var expected = Enumerable - .Take(wrapped, count0) + var expected = source + .Take(count0) .Take(count1); // Act - var result = ValueEnumerableExtensions - .Take, Wrap.Enumerator, int>(wrapped, count0) + var result = wrapped.AsValueEnumerable() + .Take(count0) .Take(count1); // Assert @@ -48,5 +48,29 @@ public void Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int .BeEnumerableOf() .BeEqualTo(expected); } + + [Theory] + [MemberData(nameof(TestData.TakeSkipEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSkipSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSkipMultiple), MemberType = typeof(TestData))] + public void Take_Skip_With_ValidData_Must_Succeed(int[] source, int take, int skip) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Take(take) + .Skip(skip); + + // Act + var result = wrapped.AsValueEnumerable() + .Take(take) + .Skip(skip); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..022a8c5ea --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,77 @@ +using NetFabric.Assertive; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take +{ + public class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] + public void Take_With_ValidData_Must_Succeed(int[] source, int count) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Take(count); + + // Act + var result = wrapped.AsValueEnumerable() + .Take(count); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] + public void Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyCollection(source); + var expected = source + .Take(count0) + .Take(count1); + + // Act + var result = wrapped.AsValueEnumerable() + .Take(count0) + .Take(count1); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.TakeSkipEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSkipSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSkipMultiple), MemberType = typeof(TestData))] + public void Take_Skip_With_ValidData_Must_Succeed(int[] source, int take, int skip) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Take(take) + .Skip(skip); + + // Act + var result = wrapped.AsValueEnumerable() + .Take(take) + .Skip(skip); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.ValueReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.ValueReadOnlyList.Tests.cs new file mode 100644 index 000000000..3d55a108a --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Partitioning/Take/Take.ValueReadOnlyList.Tests.cs @@ -0,0 +1,77 @@ +using NetFabric.Assertive; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take +{ + public class ValueReadOnlyListTests + { + [Theory] + [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] + public void Take_With_ValidData_Must_Succeed(int[] source, int count) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Take(count); + + // Act + var result = wrapped.AsValueEnumerable() + .Take(count); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] + public void Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Take(count0) + .Take(count1); + + // Act + var result = wrapped.AsValueEnumerable() + .Take(count0) + .Take(count1); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.TakeSkipEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSkipSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSkipMultiple), MemberType = typeof(TestData))] + public void Take_Skip_With_ValidData_Must_Succeed(int[] source, int take, int skip) + { + // Arrange + var wrapped = Wrap + .AsValueReadOnlyList(source); + var expected = source + .Take(take) + .Skip(skip); + + // Act + var result = wrapped.AsValueEnumerable() + .Take(take) + .Skip(skip); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs similarity index 57% rename from NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs index bd62a9833..4594c50e4 100644 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs @@ -15,8 +15,8 @@ public void Select_With_NullArray_Must_Succeed() var expected = Enumerable.Empty(); // Act - var result = ArrayExtensions - .Select(source, item => item.ToString()); + var result = source.AsValueEnumerable() + .Select(item => item.ToString()); // Assert _ = result.Must() @@ -34,12 +34,12 @@ public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, // Arrange var (offset, count) = Utils.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Select(wrapped, selector); + var expected = wrapped + .Select(selector); // Act - var result = ArrayExtensions - .Select(wrapped, selector); + var result = wrapped.AsValueEnumerable() + .Select(selector); // Assert _ = result.Must() @@ -47,5 +47,29 @@ public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, .BeEqualTo(expected, testRefStructs: false); _ = result.SequenceEqual(expected).Must().BeTrue(); } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take) + { + // Arrange + var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var wrapped = new ArraySegment(source, offset, count); + var expected = Enumerable + .Select(wrapped, item => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(item => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.AsyncValueEnumerable.Tests.cs new file mode 100644 index 000000000..402ef5f75 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.AsyncValueEnumerable.Tests.cs @@ -0,0 +1,55 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.Select +{ + public class AsyncValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] + public void Select_Selector_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Select(selector); + + // Act + var result = wrapped + .Select, Wrap.AsyncEnumerator, int, string>(selector.AsAsync()); + + // Assert + _ = result.Must() + .BeAsyncEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public async Task Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Select(item => item) + .Sum(); + + // Act + var result = await wrapped + .Select, Wrap.AsyncEnumerator, int, int>((item, _) => new ValueTask(item)) + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs new file mode 100644 index 000000000..7d68c66ec --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs @@ -0,0 +1,54 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.Select +{ + public class ReadOnlyMemoryTests + { + [Theory] + [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); + _ = result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Select(item => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(item => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ReadOnlySpan.Tests.cs new file mode 100644 index 000000000..24fcf71a2 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ReadOnlySpan.Tests.cs @@ -0,0 +1,51 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.Select +{ + public class ReadOnlySpanTests + { + [Theory] + [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(selector); + + // Assert + _ = result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(item => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(item => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ValueEnumerable.Tests.cs new file mode 100644 index 000000000..c0319c5a0 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ValueEnumerable.Tests.cs @@ -0,0 +1,53 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.Select +{ + public class ValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Select(selector); + + // Act + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Select(item => item) + .Sum(); + + // Act + var result = wrapped + .Select, Wrap.Enumerator, int, int>(item => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..9701c8224 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,53 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.Select +{ + public class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Select(item => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(item => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ValueReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ValueReadOnlyList.Tests.cs new file mode 100644 index 000000000..8de01e3b1 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/Select/Select.ValueReadOnlyList.Tests.cs @@ -0,0 +1,53 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.Select +{ + public class ValueReadOnlyListTests + { + [Theory] + [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyList(source); + var expected = source + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyList(source); + var expected = source + .Select(item => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(item => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs similarity index 56% rename from NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs index 8b159f017..c6f2db9b6 100644 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs @@ -15,8 +15,8 @@ public void Select_With_NullArray_Must_Succeed() var expected = Enumerable.Empty(); // Act - var result = ArrayExtensions - .Select(source, (item, _) => item.ToString()); + var result = source.AsValueEnumerable() + .Select((item, _) => item.ToString()); // Assert _ = result.Must() @@ -34,12 +34,12 @@ public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, // Arrange var (offset, count) = Utils.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Select(wrapped, selector); + var expected = wrapped + .Select(selector); // Act - var result = ArrayExtensions - .Select(wrapped, selector); + var result = wrapped.AsValueEnumerable() + .Select(selector); // Assert _ = result.Must() @@ -47,5 +47,28 @@ public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, .BeEqualTo(expected, testRefStructs: false); _ = result.SequenceEqual(expected).Must().BeTrue(); } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take) + { + // Arrange + var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var wrapped = new ArraySegment(source, offset, count); + var expected = wrapped + .Select((item, _) => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select((item, _) => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.AsyncValueEnumerable.Tests.cs new file mode 100644 index 000000000..634973d90 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.AsyncValueEnumerable.Tests.cs @@ -0,0 +1,55 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectAt +{ + public class AsyncValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] + public void Select_Selector_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Select(selector); + + // Act + var result = wrapped + .Select, Wrap.AsyncEnumerator, int, string>(selector.AsAsync()); + + // Assert + _ = result.Must() + .BeAsyncEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public async Task Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Select((item, _) => item) + .Sum(); + + // Act + var result = await wrapped + .Select, Wrap.AsyncEnumerator, int, int>((item, _, _) => new ValueTask(item)) + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs new file mode 100644 index 000000000..3150a7fb9 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs @@ -0,0 +1,54 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectIndex +{ + public class ReadOnlyMemoryTests + { + [Theory] + [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + _ = result.SequenceEqual(expected).Must().BeTrue(); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Select((item, _) => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select((item, _) => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ReadOnlySpan.Tests.cs new file mode 100644 index 000000000..c2f51760c --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ReadOnlySpan.Tests.cs @@ -0,0 +1,52 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectIndex +{ + public class ReadOnlySpanTests + { + [Theory] + [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(selector); + + // Assert + _ = result.SequenceEqual(expected).Must().BeTrue(); + + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select((item, _) => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select((item, _) => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ValueEnumerable.Tests.cs new file mode 100644 index 000000000..e7cf789af --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ValueEnumerable.Tests.cs @@ -0,0 +1,53 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectAt +{ + public class ValueEnumerableTests + { + [Theory] + [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Select(selector); + + // Act + var result = wrapped + .Select, Wrap.Enumerator, int, string>(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Select((item, _) => item) + .Sum(); + + // Act + var result = wrapped + .Select, Wrap.Enumerator, int, int>((item, _) => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ValueReadOnlyCollection.Tests.cs new file mode 100644 index 000000000..986037a58 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ValueReadOnlyCollection.Tests.cs @@ -0,0 +1,53 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectAt +{ + public class ValueReadOnlyCollectionTests + { + [Theory] + [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); + var expected = source + .Select((item, _) => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select((item, _) => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ValueReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ValueReadOnlyList.Tests.cs new file mode 100644 index 000000000..32643b3d1 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectAt/SelectAt.ValueReadOnlyList.Tests.cs @@ -0,0 +1,53 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectAt +{ + public class ValueReadOnlyListTests + { + [Theory] + [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] + public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyList(source); + var expected = source + .Select(selector); + + // Act + var result = wrapped.AsValueEnumerable() + .Select(selector); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Select_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyList(source); + var expected = source + .Select((item, _) => item) + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Select((item, _) => item) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectVector.TestData.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectVector.TestData.cs new file mode 100644 index 000000000..9a26a513e --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectVector.TestData.cs @@ -0,0 +1,31 @@ +using System; +using System.Numerics; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + + public static TheoryData, Vector>, Func> SelectVector => + new() + { + { Array.Empty(), item => item * 2, item => item * 2 }, + { new[] { 0 }, item => item * 2, item => item * 2 }, + { new[] { 0, 1}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2, 3}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2, 3, 4}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2, 3, 4, 5}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2, 3, 4, 5, 6}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, item => item * 2, item => item * 2 }, + { new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}, item => item * 2, item => item * 2 } + }; + + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector/SelectVector.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectVector/SelectVector.ReadOnlySpan.Tests.cs similarity index 80% rename from NetFabric.Hyperlinq.UnitTests/Projection/SelectVector/SelectVector.ReadOnlySpan.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectVector/SelectVector.ReadOnlySpan.Tests.cs index 2ce26dede..e671b28b6 100644 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector/SelectVector.ReadOnlySpan.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Projection/SelectVector/SelectVector.ReadOnlySpan.Tests.cs @@ -14,12 +14,13 @@ public class ReadOnlySpanTests public void SelectVector_ToArray_With_ValidData_Must_Succeed(int[] source, Func, Vector> vectorSelector, Func selector) { // Arrange - var expected = Enumerable - .Select(source, selector) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Select(selector) .ToArray(); // Act - var result = ((ReadOnlySpan)source.AsSpan()) + var result = wrapped.AsValueEnumerable() .SelectVector(vectorSelector, selector) .ToArray(); diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.AsyncValueEnumerable.Tests.cs similarity index 57% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.AsyncValueEnumerable.Tests.cs index f33a59e38..f1a3f87cf 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.AsyncValueEnumerable.Tests.cs @@ -1,6 +1,6 @@ using NetFabric.Assertive; using System; -using System.Threading; +using System.Linq; using System.Threading.Tasks; using Xunit; @@ -12,16 +12,17 @@ public class AsyncValueEnumerableTests [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public async ValueTask AllAsync_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task AllAsync_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.All(source, predicate); + var expected = source + .All(predicate); // Act - var result = await AsyncValueEnumerableExtensions - .AllAsync, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()); + var result = await wrapped.AsAsyncValueEnumerable() + .AllAsync(predicate.AsAsync()) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -32,17 +33,18 @@ public async ValueTask AllAsync_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task AllAsync_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) == source.Length; + var expected = source + .Where(predicate) + .Count() == source.Length; // Act - var result = await AsyncValueEnumerableExtensions - .AllAsync, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()); + var result = await wrapped.AsAsyncValueEnumerable() + .AllAsync(predicate.AsAsync()) + .ConfigureAwait(false); // Assert _ = result.Must() diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.Array.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.ReadOnlySpan.Tests.cs similarity index 74% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.Array.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.ReadOnlySpan.Tests.cs index 2311f7a20..140c004fc 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.Array.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.ReadOnlySpan.Tests.cs @@ -1,11 +1,11 @@ +using NetFabric.Assertive; using System; using System.Linq; -using NetFabric.Assertive; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.All { - public class ArrayTests + public class ReadOnlySpanTests { [Theory] [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] @@ -14,11 +14,12 @@ public class ArrayTests public void All_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .All(source, predicate); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .All(predicate); // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .All(predicate); // Assert @@ -33,12 +34,12 @@ public void All_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) - .Count() == source.Length; + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate).Count() == source.Length; // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .All(predicate); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.ValueEnumerable.Tests.cs similarity index 77% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.ValueEnumerable.Tests.cs index 28f926a97..b8f0211eb 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.ValueEnumerable.Tests.cs @@ -1,5 +1,6 @@ using NetFabric.Assertive; using System; +using System.Linq; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.All @@ -14,12 +15,12 @@ public void All_With_ValidData_Must_Succeed(int[] source, Func predic { // Arrange var wrapped = Wrap.AsValueEnumerable(source); - var expected = - System.Linq.Enumerable.All(wrapped, predicate); + var expected = source + .All(predicate); // Act - var result = ValueEnumerableExtensions - .All, Wrap.Enumerator, int>(wrapped, predicate); + var result = wrapped + .All, Wrap.Enumerator, int>(predicate); // Assert _ = result.Must() @@ -34,13 +35,12 @@ public void All_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate); + var result = wrapped + .All, Wrap.Enumerator, int>(predicate); // Assert _ = result.Must() diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.ValueReadOnlyCollection.Tests.cs similarity index 67% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ValueReadOnlyCollection.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.ValueReadOnlyCollection.Tests.cs index 38dde2cb7..62347904c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/All/All.ValueReadOnlyCollection.Tests.cs @@ -1,7 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; using NetFabric.Assertive; +using System; +using System.Linq; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.All @@ -16,12 +15,12 @@ public void All_With_ValidData_Must_Succeed(int[] source, Func predic { // Arrange var wrapped = Wrap.AsValueReadOnlyCollection(source); - var expected = - System.Linq.Enumerable.All(wrapped, predicate); + var expected = source + .All(predicate); // Act - var result = ValueReadOnlyCollectionExtensions - .All, Wrap.Enumerator, int>(wrapped, predicate); + var result = wrapped.AsValueEnumerable() + .All(predicate); // Assert _ = result.Must() @@ -36,13 +35,12 @@ public void All_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate); + var result = wrapped.AsValueEnumerable() + .All(predicate); // Assert _ = result.Must() diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.AsyncValueEnumerable.Tests.cs similarity index 56% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.AsyncValueEnumerable.Tests.cs index 7214fb810..8e3e150d3 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.AsyncValueEnumerable.Tests.cs @@ -1,9 +1,7 @@ +using NetFabric.Assertive; using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; +using System.Linq; using System.Threading.Tasks; -using NetFabric.Assertive; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any @@ -14,16 +12,17 @@ public class AsyncValueEnumerableTests [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask AnyAsync_With_ValidData_Must_Succeed(int[] source) + public async Task AnyAsync_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.Any(source); + var expected = source + .Any(); // Act - var result = await AsyncValueEnumerableExtensions - .AnyAsync, Wrap.AsyncEnumerator, int>(wrapped); + var result = await wrapped.AsAsyncValueEnumerable() + .AnyAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -34,16 +33,17 @@ public async ValueTask AnyAsync_With_ValidData_Must_Succeed(int[] source) [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public async ValueTask AnyAsync_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task AnyAsync_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.Any(source, predicate); + var expected = source + .Any(predicate); // Act - var result = await AsyncValueEnumerableExtensions - .AnyAsync, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()); + var result = await wrapped.AsAsyncValueEnumerable() + .AnyAsync(predicate.AsAsync()) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -54,17 +54,18 @@ public async ValueTask AnyAsync_Predicate_With_ValidData_Must_Succeed(int[] sour [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public async ValueTask AnyAsync_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) + public async Task AnyAsync_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) != 0; + var expected = source + .Where(predicate) + .Count() != 0; // Act - var result = await AsyncValueEnumerableExtensions - .AnyAsync, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()); + var result = await wrapped.AsAsyncValueEnumerable() + .AnyAsync(predicate.AsAsync()) + .ConfigureAwait(false); // Assert _ = result.Must() diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.Array.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.ReadOnlySpan.Tests.cs similarity index 75% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.Array.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.ReadOnlySpan.Tests.cs index 1fb74b14f..4a126ae32 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.Array.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.ReadOnlySpan.Tests.cs @@ -5,7 +5,7 @@ namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any { - public class ArrayTests + public class ReadOnlySpanTests { [Theory] @@ -15,11 +15,12 @@ public class ArrayTests public void Any_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .Any(source); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Any(); // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Any(); // Assert @@ -34,11 +35,12 @@ public void Any_With_ValidData_Must_Succeed(int[] source) public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Any(source, predicate); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Any(predicate); // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Any(predicate); // Assert @@ -53,12 +55,12 @@ public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange - var expected = Enumerable - .Where(source, predicate) - .Count() != 0; + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Where(predicate).Count() != 0; // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Any(predicate); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.ValueEnumerable.Tests.cs similarity index 79% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.ValueEnumerable.Tests.cs index 7d0a2daa1..6beda5330 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.ValueEnumerable.Tests.cs @@ -1,7 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; using NetFabric.Assertive; +using System; +using System.Linq; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any @@ -17,11 +16,11 @@ public void Any_With_ValidData_Must_Succeed(int[] source) // Arrange var wrapped = Wrap.AsValueEnumerable(source); var expected = - System.Linq.Enumerable.Any(source); + source.Any(); // Act - var result = ValueEnumerableExtensions - .Any, Wrap.Enumerator, int>(wrapped); + var result = wrapped + .Any, Wrap.Enumerator, int>(); // Assert _ = result.Must() @@ -37,11 +36,11 @@ public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate); + var result = wrapped + .Any, Wrap.Enumerator, int>(predicate); // Assert _ = result.Must() @@ -57,12 +56,11 @@ public void Any_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func, Wrap.Enumerator, int>(wrapped, predicate); + var result = wrapped + .Any, Wrap.Enumerator, int>(predicate); // Assert _ = result.Must() diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.Memory.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.ValueReadOnlyCollection.Tests.cs similarity index 77% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.Memory.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.ValueReadOnlyCollection.Tests.cs index e5adff14b..fce077d62 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.Memory.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Any/Any.ValueReadOnlyCollection.Tests.cs @@ -1,12 +1,12 @@ using NetFabric.Assertive; using System; +using System.Linq; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any { - public class MemoryTests + public class ValueReadOnlyCollectionTests { - [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] @@ -14,11 +14,12 @@ public class MemoryTests public void Any_With_ValidData_Must_Succeed(int[] source) { // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); var expected = - System.Linq.Enumerable.Any(source); + source.Any(); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Any(); // Assert @@ -33,11 +34,12 @@ public void Any_With_ValidData_Must_Succeed(int[] source) public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); var expected = - System.Linq.Enumerable.Any(source, predicate); + wrapped.Any(predicate); // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Any(predicate); // Assert @@ -52,12 +54,12 @@ public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) { // Arrange + var wrapped = Wrap.AsValueReadOnlyCollection(source); var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) != 0; + source.Where(predicate).Count() != 0; // Act - var result = source.AsMemory().AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Any(predicate); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.AsyncValueEnumerable.Tests.cs similarity index 56% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.AsyncValueEnumerable.Tests.cs index 89bf1b66d..441ac2da5 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.AsyncValueEnumerable.Tests.cs @@ -1,8 +1,7 @@ -using System; +using NetFabric.Assertive; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using NetFabric.Assertive; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.ContainsAsync @@ -13,15 +12,16 @@ public class AsyncValueEnumerableTests [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ContainsAsync_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) + public async Task ContainsAsync_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; var wrapped = Wrap.AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .ContainsAsync, Wrap.AsyncEnumerator, int>(wrapped, value); + var result = await wrapped.AsAsyncValueEnumerable() + .ContainsAsync(value) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -32,15 +32,16 @@ public async ValueTask ContainsAsync_ValueType_With_Null_And_NotContains_Must_Re [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ContainsAsync_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) + public async Task ContainsAsync_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = default(string); + const string? value = default; var wrapped = Wrap.AsAsyncValueEnumerable(source.Select(item => item.ToString()).ToArray()); // Act - var result = await AsyncValueEnumerableExtensions - .ContainsAsync, Wrap.AsyncEnumerator, string>(wrapped, value); + var result = await wrapped.AsAsyncValueEnumerable() + .ContainsAsync(value) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -50,15 +51,17 @@ public async ValueTask ContainsAsync_ReferenceType_With_Null_And_NotContains_Mus [Theory] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ContainsAsync_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source) + public async Task ContainsAsync_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = Enumerable.Last(source); + var value = source + .Last(); var wrapped = Wrap.AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .ContainsAsync, Wrap.AsyncEnumerator, int>(wrapped, value); + var result = await wrapped.AsAsyncValueEnumerable() + .ContainsAsync(value) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -68,15 +71,18 @@ public async ValueTask ContainsAsync_ValueType_With_Null_And_Contains_Must_Retur [Theory] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ContainsAsync_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source) + public async Task ContainsAsync_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = Enumerable.Last(source).ToString(); + var value = source + .Last() + .ToString(); var wrapped = Wrap.AsAsyncValueEnumerable(source.Select(item => item.ToString()).ToArray()); // Act - var result = await AsyncValueEnumerableExtensions - .ContainsAsync, Wrap.AsyncEnumerator, string>(wrapped, value); + var result = await wrapped.AsAsyncValueEnumerable() + .ContainsAsync(value) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -87,15 +93,16 @@ public async ValueTask ContainsAsync_ReferenceType_With_Null_And_Contains_Must_R [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ContainsAsync_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source) + public async Task ContainsAsync_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; var wrapped = Wrap.AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .ContainsAsync, Wrap.AsyncEnumerator, int>(wrapped, value, EqualityComparer.Default); + var result = await wrapped.AsAsyncValueEnumerable() + .ContainsAsync(value, EqualityComparer.Default) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -105,15 +112,17 @@ public async ValueTask ContainsAsync_With_DefaultComparer_And_NotContains_Must_R [Theory] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ContainsAsync_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source) + public async Task ContainsAsync_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = Enumerable.Last(source); + var value = source + .Last(); var wrapped = Wrap.AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .ContainsAsync, Wrap.AsyncEnumerator, int>(wrapped, value, EqualityComparer.Default); + var result = await wrapped.AsAsyncValueEnumerable() + .ContainsAsync(value, EqualityComparer.Default) + .ConfigureAwait(false); // Assert _ = result.Must() @@ -125,37 +134,46 @@ public async ValueTask ContainsAsync_With_DefaultComparer_And_Contains_Must_Retu [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ContainsAsync_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) + public async Task ContainsAsync_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; + var comparer = new TestComparer(); var wrapped = Wrap.AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .ContainsAsync, Wrap.AsyncEnumerator, int>(wrapped, value, TestComparer.Instance); + var result = await wrapped.AsAsyncValueEnumerable() + .ContainsAsync(value, comparer) + .ConfigureAwait(false); // Assert _ = result.Must() .BeFalse(); + _ = comparer.EqualsCounter.Must() + .BeEqualTo(source.Length); } [Theory] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ContainsAsync_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) + public async Task ContainsAsync_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = Enumerable.Last(source); + var value = source + .Last(); + var comparer = new TestComparer(); var wrapped = Wrap.AsAsyncValueEnumerable(source); // Act - var result = await AsyncValueEnumerableExtensions - .ContainsAsync, Wrap.AsyncEnumerator, int>(wrapped, value, TestComparer.Instance); + var result = await wrapped.AsAsyncValueEnumerable() + .ContainsAsync(value, comparer) + .ConfigureAwait(false); // Assert _ = result.Must() .BeTrue(); + _ = comparer.EqualsCounter.Must() + .BeEqualTo(source.Length); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.Array.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.ReadOnlySpan.Tests.cs similarity index 74% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.Array.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.ReadOnlySpan.Tests.cs index d5409687f..63e3ff40b 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.Array.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.ReadOnlySpan.Tests.cs @@ -1,12 +1,12 @@ +using NetFabric.Assertive; using System; using System.Collections.Generic; using System.Linq; -using NetFabric.Assertive; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Contains { - public class ArrayTests + public class ReadOnlySpanTests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -15,10 +15,11 @@ public class ArrayTests public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Contains(value); // Assert @@ -33,8 +34,8 @@ public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = default(string); - var wrapped = source.Select(item => item.ToString()).ToArray(); + const string? value = default; + var wrapped = source.AsValueEnumerable().Select(item => item.ToString()).ToArray(); // Act var result = wrapped.AsValueEnumerable() @@ -52,9 +53,10 @@ public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] sour { // Arrange var value = source.Last(); - + var wrapped = (ReadOnlySpan)source.AsSpan(); + // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Contains(value); // Assert @@ -69,7 +71,7 @@ public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] { // Arrange var value = source.Last().ToString(); - var wrapped = source.Select(item => item.ToString()).ToArray(); + var wrapped = source.AsValueEnumerable().Select(item => item.ToString()).ToArray(); // Act var result = wrapped.AsValueEnumerable() @@ -87,10 +89,11 @@ public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Contains(value, EqualityComparer.Default); // Assert @@ -105,9 +108,10 @@ public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] sou { // Arrange var value = source.Last(); + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Contains(value, EqualityComparer.Default); // Assert @@ -122,15 +126,19 @@ public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] sou public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; + var comparer = new TestComparer(); + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsValueEnumerable() - .Contains(value, TestComparer.Instance); + var result = wrapped.AsValueEnumerable() + .Contains(value, comparer); // Assert _ = result.Must() .BeFalse(); + _ = comparer.EqualsCounter.Must() + .BeEqualTo(source.Length); } [Theory] @@ -140,14 +148,18 @@ public void Contains_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) { // Arrange var value = source.Last(); + var comparer = new TestComparer(); + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = source.AsValueEnumerable() - .Contains(value, TestComparer.Instance); + var result = wrapped.AsValueEnumerable() + .Contains(value, comparer); // Assert _ = result.Must() .BeTrue(); + _ = comparer.EqualsCounter.Must() + .BeEqualTo(source.Length); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.ValueEnumerable.Tests.cs similarity index 78% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.ValueEnumerable.Tests.cs index b4a85bd10..3aaf3b99c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.ValueEnumerable.Tests.cs @@ -1,7 +1,6 @@ -using System; +using NetFabric.Assertive; using System.Collections.Generic; using System.Linq; -using NetFabric.Assertive; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Contains @@ -15,12 +14,12 @@ public class ValueEnumerableTests public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; var wrapped = Wrap.AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value); + var result = wrapped + .Contains, Wrap.Enumerator, int>(value); // Assert _ = result.Must() @@ -34,12 +33,12 @@ public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = default(string); + const string? value = default; var wrapped = Wrap.AsValueEnumerable(source.Select(item => item.ToString()).ToArray()); // Act - var result = ValueEnumerableExtensions - .Contains, Wrap.Enumerator, string>(wrapped, value); + var result = wrapped + .Contains, Wrap.Enumerator, string>(value); // Assert _ = result.Must() @@ -52,12 +51,13 @@ public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(in public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = Enumerable.Last(source); + var value = source + .Last(); var wrapped = Wrap.AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value); + var result = wrapped + .Contains, Wrap.Enumerator, int>(value); // Assert _ = result.Must() @@ -70,12 +70,14 @@ public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] sour public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = Enumerable.Last(source).ToString(); + var value = source + .Last() + .ToString(); var wrapped = Wrap.AsValueEnumerable(source.Select(item => item.ToString()).ToArray()); // Act - var result = ValueEnumerableExtensions - .Contains, Wrap.Enumerator, string>(wrapped, value); + var result = wrapped + .Contains, Wrap.Enumerator, string>(value); // Assert _ = result.Must() @@ -89,12 +91,12 @@ public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; var wrapped = Wrap.AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value, EqualityComparer.Default); + var result = wrapped + .Contains, Wrap.Enumerator, int>(value, EqualityComparer.Default); // Assert _ = result.Must() @@ -107,12 +109,13 @@ public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = Enumerable.Last(source); + var value = source + .Last(); var wrapped = Wrap.AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value, EqualityComparer.Default); + var result = wrapped + .Contains, Wrap.Enumerator, int>(value, EqualityComparer.Default); // Assert _ = result.Must() @@ -126,16 +129,19 @@ public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] sou public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; + var comparer = new TestComparer(); var wrapped = Wrap.AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value, TestComparer.Instance); + var result = wrapped + .Contains, Wrap.Enumerator, int>(value, comparer); // Assert _ = result.Must() .BeFalse(); + _ = comparer.EqualsCounter.Must() + .BeEqualTo(source.Length); } [Theory] @@ -144,16 +150,20 @@ public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source public void Contains_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = Enumerable.Last(source); + var value = source + .Last(); + var comparer = new TestComparer(); var wrapped = Wrap.AsValueEnumerable(source); // Act - var result = ValueEnumerableExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value, TestComparer.Instance); + var result = wrapped + .Contains, Wrap.Enumerator, int>(value, comparer); // Assert _ = result.Must() .BeTrue(); + _ = comparer.EqualsCounter.Must() + .BeEqualTo(source.Length); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.ValueReadOnlyCollection.Tests.cs similarity index 68% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ValueReadOnlyCollection.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.ValueReadOnlyCollection.Tests.cs index 4b0bfc620..aba068ab1 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/Contains/Contains.ValueReadOnlyCollection.Tests.cs @@ -1,6 +1,6 @@ -using System; -using System.Collections.Generic; using NetFabric.Assertive; +using System.Collections.Generic; +using System.Linq; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Contains @@ -14,12 +14,12 @@ public class ValueReadOnlyCollectionTests public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; var wrapped = Wrap.AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value); + var result = wrapped.AsValueEnumerable() + .Contains(value); // Assert _ = result.Must() @@ -33,12 +33,12 @@ public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = default(string); - var wrapped = Wrap.AsValueReadOnlyCollection(source.AsValueEnumerable().Select(item => item.ToString()).ToArray()); + const string? value = default; + var wrapped = Wrap.AsValueReadOnlyCollection(source.Select(item => item.ToString()).ToArray()); // Act - var result = ValueReadOnlyCollectionExtensions - .Contains, Wrap.Enumerator, string>(wrapped, value); + var result = wrapped.AsValueEnumerable() + .Contains(value); // Assert _ = result.Must() @@ -51,12 +51,13 @@ public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(in public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = System.Linq.Enumerable.Last(source); + var value = source + .Last(); var wrapped = Wrap.AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value); + var result = wrapped.AsValueEnumerable() + .Contains(value); // Assert _ = result.Must() @@ -69,12 +70,14 @@ public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] sour public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = System.Linq.Enumerable.Last(source).ToString(); + var value = source + .Last() + .ToString(); var wrapped = Wrap.AsValueReadOnlyCollection(source.AsValueEnumerable().Select(item => item.ToString()).ToArray()); // Act - var result = ValueReadOnlyCollectionExtensions - .Contains, Wrap.Enumerator, string>(wrapped, value); + var result = wrapped.AsValueEnumerable() + .Contains(value); // Assert _ = result.Must() @@ -88,12 +91,12 @@ public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; var wrapped = Wrap.AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value, EqualityComparer.Default); + var result = wrapped.AsValueEnumerable() + .Contains(value, EqualityComparer.Default); // Assert _ = result.Must() @@ -106,12 +109,13 @@ public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = System.Linq.Enumerable.Last(source); + var value = source + .Last(); var wrapped = Wrap.AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value, EqualityComparer.Default); + var result = wrapped.AsValueEnumerable() + .Contains(value, EqualityComparer.Default); // Assert _ = result.Must() @@ -125,16 +129,19 @@ public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] sou public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; + var comparer = new TestComparer(); var wrapped = Wrap.AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value, TestComparer.Instance); + var result = wrapped.AsValueEnumerable() + .Contains(value, comparer); // Assert _ = result.Must() .BeFalse(); + _ = comparer.EqualsCounter.Must() + .BeEqualTo(source.Length); } [Theory] @@ -143,16 +150,20 @@ public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source public void Contains_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = System.Linq.Enumerable.Last(source); + var value = source + .Last(); + var comparer = new TestComparer(); var wrapped = Wrap.AsValueReadOnlyCollection(source); // Act - var result = ValueReadOnlyCollectionExtensions - .Contains, Wrap.Enumerator, int>(wrapped, value, TestComparer.Instance); + var result = wrapped.AsValueEnumerable() + .Contains(value, comparer); // Assert _ = result.Must() .BeTrue(); + _ = comparer.EqualsCounter.Must() + .BeEqualTo(source.Length); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.Tests.cs similarity index 76% rename from NetFabric.Hyperlinq.UnitTests/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.Tests.cs index 7b1465500..f78d79f91 100644 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.Tests.cs @@ -1,5 +1,6 @@ using NetFabric.Assertive; using System; +using System.Linq; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Quantifier.ContainsVector @@ -14,10 +15,11 @@ public class ReadOnlySpanTests public void ContainsVector_With_NotContains_Must_ReturnFalse(int[] source) { // Arrange - var value = int.MaxValue; + const int value = int.MaxValue; + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = ((ReadOnlySpan)source.AsSpan()) + var result = wrapped.AsValueEnumerable() .ContainsVector(value); // Assert @@ -31,10 +33,12 @@ public void ContainsVector_With_NotContains_Must_ReturnFalse(int[] source) public void ContainsVector_With_Contains_Must_ReturnTrue(int[] source) { // Arrange - var value = System.Linq.Enumerable.Last(source); + var value = source + .Last(); + var wrapped = (ReadOnlySpan)source.AsSpan(); // Act - var result = ((ReadOnlySpan)source.AsSpan()) + var result = wrapped.AsValueEnumerable() .ContainsVector(value); // Assert diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs similarity index 70% rename from NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs index e2afa1218..210557769 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs @@ -16,8 +16,8 @@ public void Distinct_With_NullArray_Must_Succeed() var expected = Enumerable.Empty(); // Act - var result = ArrayExtensions - .Distinct(source); + var result = source.AsValueEnumerable() + .Distinct(); // Assert _ = result.Must() @@ -35,12 +35,12 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source, int skip, int tak // Arrange var (offset, count) = Utils.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Distinct(wrapped); + var expected = wrapped + .Distinct(); // Act - var result = ArrayExtensions - .Distinct(wrapped); + var result = wrapped.AsValueEnumerable() + .Distinct(); // Assert _ = result.Must() @@ -58,13 +58,13 @@ public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source, int skip, // Arrange var (offset, count) = Utils.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Distinct(wrapped) + var expected = wrapped + .Distinct() .ToArray(); // Act - var result = ArrayExtensions - .Distinct(wrapped) + var result = wrapped.AsValueEnumerable() + .Distinct() .ToArray(); // Assert @@ -80,16 +80,16 @@ public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source, int skip, public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source, int skip, int take) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var (offset, count) = Utils.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Distinct(wrapped) + var expected = wrapped + .Distinct() .ToArray(); // Act - using var result = ArrayExtensions - .Distinct(wrapped) + using var result = wrapped.AsValueEnumerable() + .Distinct() .ToArray(pool); // Assert @@ -106,13 +106,13 @@ public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source, int skip, // Arrange var (offset, count) = Utils.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Distinct(wrapped) + var expected = wrapped + .Distinct() .ToList(); // Act - var result = ArrayExtensions - .Distinct(wrapped) + var result = wrapped.AsValueEnumerable() + .Distinct() .ToList(); // Assert @@ -120,5 +120,28 @@ public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source, int skip, .BeEnumerableOf() .BeEqualTo(expected); } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take) + { + // Arrange + var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var wrapped = new ArraySegment(source, offset, count); + var expected = wrapped + .Distinct() + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Distinct() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs similarity index 52% rename from NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs index e693720cc..5617efc0b 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs @@ -1,5 +1,6 @@ using NetFabric.Assertive; using System.Buffers; +using System.Linq; using System.Threading.Tasks; using Xunit; @@ -15,12 +16,12 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.Distinct(source); + var expected = source + .Distinct(); // Act - var result = AsyncValueEnumerableExtensions - .Distinct, Wrap.AsyncEnumerator, int>(wrapped); + var result = wrapped.AsAsyncValueEnumerable() + .Distinct(); // Assert _ = result.Must() @@ -32,18 +33,19 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source) [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask Distinct_ToArrayAsync_With_ValidData_Must_Succeed(int[] source) + public async Task Distinct_ToArrayAsync_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.ToArray( - System.Linq.Enumerable.Distinct(source)); + var expected = source + .Distinct() + .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Distinct, Wrap.AsyncEnumerator, int>(wrapped) - .ToArrayAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Distinct() + .ToArrayAsync() + .ConfigureAwait(false); // Assert _ = result.Must() @@ -55,19 +57,20 @@ public async ValueTask Distinct_ToArrayAsync_With_ValidData_Must_Succeed(int[] s [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask Distinct_ToArrayAsync_MemoryPool_With_ValidData_Must_Succeed(int[] source) + public async Task Distinct_ToArrayAsync_MemoryPool_With_ValidData_Must_Succeed(int[] source) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.ToArray( - System.Linq.Enumerable.Distinct(source)); + var expected = source + .Distinct() + .ToArray(); // Act - var result = await AsyncValueEnumerableExtensions - .Distinct, Wrap.AsyncEnumerator, int>(wrapped) - .ToArrayAsync(pool); + var result = await wrapped.AsAsyncValueEnumerable() + .Distinct() + .ToArrayAsync(pool) + .ConfigureAwait(false); // Assert _ = result @@ -78,23 +81,47 @@ public async ValueTask Distinct_ToArrayAsync_MemoryPool_With_ValidData_Must_Succ [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask Distinct_ToListAsync_With_ValidData_Must_Succeed(int[] source) + public async Task Distinct_ToListAsync_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.ToList( - System.Linq.Enumerable.Distinct(source)); + var expected = source + .Distinct() + .ToList(); // Act - var result = await AsyncValueEnumerableExtensions - .Distinct, Wrap.AsyncEnumerator, int>(wrapped) - .ToListAsync(); + var result = await wrapped.AsAsyncValueEnumerable() + .Distinct() + .ToListAsync() + .ConfigureAwait(false); // Assert _ = result.Must() .BeEnumerableOf() .BeEqualTo(expected); } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public async Task Distinct_SumAsync_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsAsyncValueEnumerable(source); + var expected = source + .Distinct() + .Sum(); + + // Act + var result = await wrapped.AsAsyncValueEnumerable() + .Distinct() + .SumAsync() + .ConfigureAwait(false); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.Array.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs similarity index 65% rename from NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.Array.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs index 052cf32d6..9f280e6d5 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.Array.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs @@ -1,34 +1,13 @@ using NetFabric.Assertive; using System; using System.Buffers; -using System.Collections.Generic; using System.Linq; using Xunit; namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct { - public class ArrayTests + public class ReadOnlyMemoryTests { - [Theory] - [InlineData(200)] - public void Distinct_With_LargeData_Must_Succeed(int count) - { - // Arrange - var source = ValueEnumerable.Range(0, count).ToArray(); - var expected = Enumerable - .Distinct(source); - - // Act - var result = source.AsValueEnumerable() - .Distinct(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] @@ -36,11 +15,12 @@ public void Distinct_With_LargeData_Must_Succeed(int count) public void Distinct_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .Distinct(source); + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Distinct(); // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Distinct(); // Assert @@ -57,12 +37,12 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source) public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .Distinct(source) - .ToArray(); + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = + source.Distinct().ToArray(); // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Distinct() .ToArray(); @@ -79,20 +59,20 @@ public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source) { // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Distinct(source) + var pool = ArrayPool.Shared; + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Distinct() .ToArray(); // Act - using var result = source.AsValueEnumerable() + using var result = wrapped.AsValueEnumerable() .Distinct() .ToArray(pool); // Assert _ = result - .SequenceEqual(expected) - .Must().BeTrue(); + .SequenceEqual(expected); } [Theory] @@ -102,20 +82,42 @@ public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .Distinct(source) + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Distinct() .ToList(); // Act - var result = source.AsValueEnumerable() + var result = wrapped.AsValueEnumerable() .Distinct() .ToList(); // Assert _ = result.Must() - .BeOfType>() .BeEnumerableOf() .BeEqualTo(expected); } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = (ReadOnlyMemory)source.AsMemory(); + var expected = source + .Distinct() + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Distinct() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs similarity index 70% rename from NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs index 1b6b18661..4dfb50115 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs @@ -15,12 +15,13 @@ public class ReadOnlySpanTests public void Distinct_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .Distinct(source); + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Distinct(); // Act - var result = ArrayExtensions - .Distinct((ReadOnlySpan)source.AsSpan()); + var result = wrapped.AsValueEnumerable() + .Distinct(); // Assert _ = result.SequenceEqual(expected).Must().BeTrue(); @@ -33,13 +34,14 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source) public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .Distinct(source) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Distinct() .ToArray(); // Act - var result = ArrayExtensions - .Distinct((ReadOnlySpan)source.AsSpan()) + var result = wrapped.AsValueEnumerable() + .Distinct() .ToArray(); // Assert @@ -55,17 +57,19 @@ public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .Distinct(source) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Distinct() .ToArray(); // Act - using var result = ArrayExtensions - .Distinct((ReadOnlySpan)source.AsSpan()) - .ToArray(MemoryPool.Shared); + using var result = wrapped.AsValueEnumerable() + .Distinct() + .ToArray(ArrayPool.Shared); // Assert - _ = result.Memory.Must() + _ = result.Must() + .BeEnumerableOf() .BeEqualTo(expected); } @@ -76,13 +80,14 @@ public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) { // Arrange - var expected = Enumerable - .Distinct(source) + var wrapped = (ReadOnlySpan)source.AsSpan(); + var expected = source + .Distinct() .ToList(); // Act - var result = ArrayExtensions - .Distinct((ReadOnlySpan)source.AsSpan()) + var result = wrapped.AsValueEnumerable() + .Distinct() .ToList(); // Assert @@ -90,5 +95,6 @@ public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) .BeEnumerableOf() .BeEqualTo(expected); } + } } diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs similarity index 63% rename from NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs index 9e67dfb2a..1f224ea32 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs @@ -15,12 +15,12 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap.AsValueEnumerable(source); - var expected = Enumerable - .Distinct(wrapped); + var expected = source + .Distinct(); // Act - var result = ValueEnumerableExtensions - .Distinct, Wrap.Enumerator, int>(wrapped); + var result = wrapped.AsValueEnumerable() + .Distinct(); // Assert _ = result.Must() @@ -36,13 +36,13 @@ public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap.AsValueEnumerable(source); - var expected = Enumerable - .Distinct(source) + var expected = source + .Distinct() .ToArray(); // Act - var result = ValueEnumerableExtensions - .Distinct, Wrap.Enumerator, int>(wrapped) + var result = wrapped.AsValueEnumerable() + .Distinct() .ToArray(); // Assert @@ -58,20 +58,21 @@ public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source) { // Arrange - var pool = MemoryPool.Shared; + var pool = ArrayPool.Shared; var wrapped = Wrap.AsValueEnumerable(source); - var expected = Enumerable - .Distinct(source) + var expected = source + .Distinct() .ToArray(); // Act - using var result = ValueEnumerableExtensions - .Distinct, Wrap.Enumerator, int>(wrapped) + using var result = wrapped.AsValueEnumerable() + .Distinct() .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); } [Theory] @@ -82,13 +83,13 @@ public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap.AsValueEnumerable(source); - var expected = Enumerable - .Distinct(source) + var expected = source + .Distinct() .ToList(); // Act - var result = ValueEnumerableExtensions - .Distinct, Wrap.Enumerator, int>(wrapped) + var result = wrapped.AsValueEnumerable() + .Distinct() .ToList(); // Assert @@ -96,5 +97,27 @@ public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) .BeEnumerableOf() .BeEqualTo(expected); } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap.AsValueEnumerable(source); + var expected = source + .Distinct() + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Distinct() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } } } diff --git a/NetFabric.Hyperlinq.Core.UnitTests/TestData/TestData.Empty.cs b/NetFabric.Hyperlinq.Core.UnitTests/TestData/TestData.Empty.cs new file mode 100644 index 000000000..b9cab86e8 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/TestData/TestData.Empty.cs @@ -0,0 +1,259 @@ +using System; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + public static TheoryData Empty => + new() + { + Array.Empty() + }; + + public static TheoryData SkipEmpty => + new() + { + { Array.Empty(), -1 }, + { Array.Empty(), 0 }, + { Array.Empty(), 1 }, + + { new[] { 1 }, 1 }, + { new[] { 1 }, 5 }, + + { new[] { 0, 1, 2 }, 3 }, + { new[] { 0, 1, 2 }, 5 } + }; + + public static TheoryData TakeEmpty => + new() + { + { Array.Empty(), -1 }, + { Array.Empty(), 0 }, + { Array.Empty(), 1 }, + + { new[] { 5 }, -1 }, + { new[] { 5 }, 0 }, + + { new[] { 0, 1, 2, 3, 4, 5 }, -1 }, + { new[] { 0, 1, 2, 3, 4, 5 }, 0 } + }; + + public static TheoryData SkipTakeEmpty => + new() + { + { Array.Empty(), -1, -1 }, + { Array.Empty(), -1, 0 }, + { Array.Empty(), 0, -1 }, + { Array.Empty(), 0, 0 }, + { Array.Empty(), 0, 9 }, + { Array.Empty(), 1, 0 }, + { Array.Empty(), 1, 9 }, + + { new[] { 1 }, -1, -1 }, + { new[] { 1 }, -1, 0 }, + { new[] { 1 }, 0, -1 }, + { new[] { 1 }, 0, 0 }, + { new[] { 1 }, 1, 0 }, + { new[] { 1 }, 1, 9 }, + + { new[] { 1, 2, 3, 4, 5 }, -1, -1 }, + { new[] { 1, 2, 3, 4, 5 }, -1, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 0, -1 }, + { new[] { 1, 2, 3, 4, 5 }, 2, -1 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 9, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 9, 9 } + }; + + public static TheoryData TakeSkipEmpty => + new() + { + { Array.Empty(), -1, -1 }, + { Array.Empty(), -1, 0 }, + { Array.Empty(), 0, -1 }, + { Array.Empty(), 0, 0 }, + { Array.Empty(), 9, 0 }, + { Array.Empty(), 0, 1 }, + { Array.Empty(), 9, 1 }, + + { new[] { 1 }, -1, -1 }, + { new[] { 1 }, -1, 0 }, + { new[] { 1 }, 0, -1 }, + { new[] { 1 }, 0, 0 }, + { new[] { 1 }, 0, 1 }, + { new[] { 1 }, 9, 1 }, + + { new[] { 1, 2, 3, 4, 5 }, -1, -1 }, + { new[] { 1, 2, 3, 4, 5 }, -1, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 0, -1 }, + { new[] { 1, 2, 3, 4, 5 }, -1, 2 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 2 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9 }, + { new[] { 1, 2, 3, 4, 5 }, 9, 9 } + }; + + public static TheoryData> PredicateEmpty => + new() + { + { Array.Empty(), _ => false }, + { Array.Empty(), _ => true }, + + { new[] { 1 }, _ => false }, + { new[] { 1 }, item => item > 9 }, + + { new[] { 1, 2, 3, 4, 5 }, _ => false }, + { new[] { 1, 2, 3, 4, 5 }, item => item > 9 } + }; + + public static TheoryData> SkipTakePredicateEmpty => + new() + { + { Array.Empty(), 0, 9, _ => false }, + { Array.Empty(), 0, 0, _ => true }, + { Array.Empty(), 0, 9, item => item > 9 }, + + { new[] { 1 }, 0, 0, _ => true }, + { new[] { 1 }, 9, 9, _ => true }, + { new[] { 1 }, 0, 9, _ => false }, + { new[] { 1 }, 0, 9, item => item > 9 }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 0, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 9, 9, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => false }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item > 9 } + }; + + public static TheoryData, Func> PredicatePredicateEmpty => + new() + { + { Array.Empty(), _ => true, _ => true }, + + { new[] { 1, 2, 3, 4, 5 }, _ => false, _ => false }, + { new[] { 1, 2, 3, 4, 5 }, _ => true, _ => false }, + { new[] { 1, 2, 3, 4, 5 }, _ => false, _ => true } + }; + + public static TheoryData, Func> SkipTakePredicatePredicateEmpty => + new() + { + { Array.Empty(), 0, 9, _ => true, _ => true }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => false, _ => false }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, _ => false }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => false, _ => true } + }; + + public static TheoryData> PredicateAtEmpty => + new() + { + { Array.Empty(), (_, __) => false }, + { Array.Empty(), (_, __) => true }, + + { new[] { 1 }, (_, __) => false }, + { new[] { 1 }, (item, _) => item > 9 }, + { new[] { 1 }, (_, index) => index > 9 }, + + { new[] { 1, 2, 3, 4, 5 }, (_, __) => false }, + { new[] { 1, 2, 3, 4, 5 }, (item, _) => item > 9 }, + { new[] { 1, 2, 3, 4, 5 }, (_, index) => index > 9 } + }; + + public static TheoryData> SkipTakePredicateAtEmpty => + new() + { + { Array.Empty(), 0, 9, (_, __) => false }, + { Array.Empty(), 0, 0, (_, __) => true }, + { Array.Empty(), 0, 9, (item, _) => item > 9 }, + { Array.Empty(), 0, 9, (_, index) => index > 9 }, + + { new[] { 1 }, 0, 0, (_, __) => true }, + { new[] { 1 }, 0, 9, (_, __) => false }, + { new[] { 1 }, 0, 9, (item, _) => item > 9 }, + { new[] { 1 }, 0, 9, (_, index) => index > 9 }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 0, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (_, __) => false }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (item, _) => item > 9 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (_, index) => index > 9 }, + + { new[] { 1, 2, 3, 4, 5 }, 2, 0, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, (_, __) => false }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, (item, _) => item > 9 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, (_, index) => index > 9 } + }; + + public static TheoryData> SelectorEmpty => + new() + { + { Array.Empty(), item => item.ToString() } + }; + + public static TheoryData> SkipTakeSelectorEmpty => + new() + { + { Array.Empty(), 0, 0, item => item.ToString() }, + { Array.Empty(), 0, 9, item => item.ToString() }, + + { new[] { 1 }, 0, 0, item => item.ToString() }, + { new[] { 1 }, 9, 9, item => item.ToString() }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 0, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 9, 9, item => item.ToString() } + }; + + public static TheoryData> SelectorAtEmpty => + new() + { + { Array.Empty(), (item, index) => $"{item} {index}" } + }; + + public static TheoryData> SkipTakeSelectorAtEmpty => + new() + { + { Array.Empty(), 0, 0, (item, index) => $"{item} {index}" }, + { Array.Empty(), 0, 9, (item, index) => $"{item} {index}" }, + + { new[] { 1 }, 0, 0, (item, index) => $"{item} {index}" }, + { new[] { 1 }, 9, 9, (item, index) => $"{item} {index}" }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 0, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, 9, 9, (item, index) => $"{item} {index}" } + }; + + public static TheoryData, Func> PredicateSelectorEmpty => + new() + { + { Array.Empty(), _ => false, item => item.ToString() }, + { Array.Empty(), _ => true, item => item.ToString() }, + + { new[] { 1 }, _ => false, item => item.ToString() }, + { new[] { 1 }, item => item > 9, item => item.ToString() }, + + { new[] { 1, 2, 3, 4, 5 }, _ => false, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, item => item > 9, item => item.ToString() } + }; + + public static TheoryData, Func> SkipTakePredicateSelectorEmpty => + new() + { + { Array.Empty(), 0, 9, _ => false, item => item.ToString() }, + { Array.Empty(), 0, 0, _ => true, item => item.ToString() }, + { Array.Empty(), 0, 9, item => item > 9, item => item.ToString() }, + + { new[] { 1 }, 0, 0, _ => true, item => item.ToString() }, + { new[] { 1 }, 9, 9, _ => true, item => item.ToString() }, + { new[] { 1 }, 0, 9, _ => false, item => item.ToString() }, + { new[] { 1 }, 0, 9, item => item > 9, item => item.ToString() }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 0, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 9, 9, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => false, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item > 9, item => item.ToString() } + }; + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/TestData/TestData.Multiple.cs b/NetFabric.Hyperlinq.Core.UnitTests/TestData/TestData.Multiple.cs new file mode 100644 index 000000000..ffc15736a --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/TestData/TestData.Multiple.cs @@ -0,0 +1,257 @@ +using System; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + public static TheoryData Multiple => + new() + { + new[] { 1, 2, 3, 4, 5 } + }; + + public static TheoryData SkipMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, -1 }, + { new[] { 1, 2, 3, 4, 5 }, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 2 } + }; + + public static TheoryData TakeMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, 2 }, + { new[] { 1, 2, 3, 4, 5 }, 5 }, + { new[] { 1, 2, 3, 4, 5 }, 9 } + }; + + public static TheoryData SkipTakeMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, -1, 2 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 2 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 2 }, + { new[] { 1, 2, 3, 4, 5 }, -1, 5 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 5 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 3 }, + { new[] { 1, 2, 3, 4, 5 }, -1, 9 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9 } + }; + + public static TheoryData TakeSkipMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, 2, -1 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 5, -1 }, + { new[] { 1, 2, 3, 4, 5 }, 5, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 5, 2 }, + { new[] { 1, 2, 3, 4, 5 }, 9, -1 }, + { new[] { 1, 2, 3, 4, 5 }, 9, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 9, 2 } + }; + + public static TheoryData> PredicateMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 1 } + }; + + public static TheoryData> SkipTakePredicateMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, -1, 2, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 2, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 2, 2, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, -1, 5, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 5, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 2, 3, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, -1, 9, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, _ => true }, + + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, item => (item & 0x01) == 0 }, + + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, item => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, item => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, item => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, item => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, item => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, item => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, item => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, item => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, item => (item & 0x01) == 1 } + }; + + + public static TheoryData, Func> PredicatePredicateMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, _ => true, _ => true }, + + { new[] { 1, 2, 3, 4, 5 }, _ => true, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 1, _ => true } + }; + + public static TheoryData, Func> SkipTakePredicatePredicateMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, _ => true }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, item => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => (item & 0x01) == 1, _ => true } + }; + + public static TheoryData> PredicateAtMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, (item, _) => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5 }, (item, _) => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5 }, (_, index) => (index & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5 }, (_, index) => (index & 0x01) == 1 } + }; + + public static TheoryData> SkipTakePredicateAtMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, 0, 2, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 2, 2, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, -1, 5, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 5, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 2, 3, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, -1, 9, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, (_, __) => true }, + + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, (item, _) => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, (item, _) => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, (item, _) => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, (item, _) => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, (item, _) => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, (item, _) => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, (item, _) => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, (item, _) => (item & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, (item, _) => (item & 0x01) == 0 }, + + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, (item, _) => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, (item, _) => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, (item, _) => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, (item, _) => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, (item, _) => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, (item, _) => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, (item, _) => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, (item, _) => (item & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, (item, _) => (item & 0x01) == 1 }, + + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, (_, index) => (index & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, (_, index) => (index & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, (_, index) => (index & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, (_, index) => (index & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, (_, index) => (index & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, (_, index) => (index & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, (_, index) => (index & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, (_, index) => (index & 0x01) == 0 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, (_, index) => (index & 0x01) == 0 }, + + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, (_, index) => (index & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, (_, index) => (index & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, (_, index) => (index & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, (_, index) => (index & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, (_, index) => (index & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, (_, index) => (index & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, (_, index) => (index & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, (_, index) => (index & 0x01) == 1 }, + { new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, (_, index) => (index & 0x01) == 1 } + }; + + public static TheoryData> SelectorMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, item => item.ToString() } + }; + + public static TheoryData> SkipTakeSelectorMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, -1, 2, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 2, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 2, 2, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, -1, 5, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 5, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 2, 3, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, -1, 9, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, item => item.ToString() } + }; + + public static TheoryData> SelectorAtMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, (item, index) => $"{item} {index}" } + }; + + public static TheoryData> SkipTakeSelectorAtMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, -1, 2, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, 0, 2, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, 2, 2, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, -1, 5, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, 0, 5, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, 2, 3, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, -1, 9, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, (item, index) => $"{item} {index}" } + }; + + public static TheoryData, Func> PredicateSelectorMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 0, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 1, item => item.ToString() } + }; + + public static TheoryData, Func> SkipTakePredicateSelectorMultiple => + new() + { + { new[] { 1, 2, 3, 4, 5 }, -1, 2, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 2, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 2, 2, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, -1, 5, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 5, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 2, 3, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, -1, 9, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, _ => true, item => item.ToString() }, + + { new[] { 1, 2, 3, 4, 5 }, -1, 5, item => (item & 0x01) == 0, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 5, item => (item & 0x01) == 0, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, -1, 9, item => (item & 0x01) == 0, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => (item & 0x01) == 0, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 1, 9, item => (item & 0x01) == 0, item => item.ToString() }, + + { new[] { 1, 2, 3, 4, 5 }, -1, 5, item => (item & 0x01) == 1, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 5, item => (item & 0x01) == 1, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, -1, 9, item => (item & 0x01) == 1, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => (item & 0x01) == 1, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 1, 9, item => (item & 0x01) == 1, item => item.ToString() } + }; + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/TestData/TestData.Single.cs b/NetFabric.Hyperlinq.Core.UnitTests/TestData/TestData.Single.cs new file mode 100644 index 000000000..dc39352e7 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/TestData/TestData.Single.cs @@ -0,0 +1,214 @@ +using System; +using Xunit; + +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class TestData + { + public static TheoryData Single => + new() + { + new[] { 1 } + }; + + public static TheoryData SkipSingle => + new() + { + { new[] { 1 }, -1 }, + { new[] { 1 }, 0 }, + + { new[] { 0, 1, 2 }, 2 } + }; + + public static TheoryData TakeSingle => + new() + { + { new[] { 1 }, 1 }, + + { new[] { 1, 2, 3, 4, 5 }, 1 } + }; + + public static TheoryData SkipTakeSingle => + new() + { + { new[] { 1 }, -1, 1 }, + { new[] { 1 }, 0, 1 }, + + { new[] { 1, 2, 3, 4, 5 }, -1, 1 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 1 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 1 }, + { new[] { 1, 2, 3, 4, 5 }, 4, 1 } + }; + + public static TheoryData TakeSkipSingle => + new() + { + { new[] { 1 }, 1, -1 }, + { new[] { 1 }, 1, 0 }, + + { new[] { 1, 2, 3, 4, 5 }, 1, -1 }, + { new[] { 1, 2, 3, 4, 5 }, 1, 0 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 1 }, + }; + + public static TheoryData> PredicateSingle => + new() + { + { new[] { 1 }, _ => true }, + { new[] { 1 }, item => item == 1 }, + + { new[] { 1, 2, 3, 4, 5 }, item => item == 1 }, + { new[] { 1, 2, 3, 4, 5 }, item => item == 3 }, + { new[] { 1, 2, 3, 4, 5 }, item => item == 5 } + }; + + public static TheoryData> SkipTakePredicateSingle => + new() + { + { new[] { 1 }, -1, 9, _ => true }, + { new[] { 1 }, 0, 1, _ => true }, + { new[] { 1 }, 0, 9, _ => true }, + { new[] { 1 }, 0, 9, item => item == 1 }, + + { new[] { 1, 2, 3, 4, 5 }, -1, 1, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 1, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 2, 1, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 4, 1, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 1 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 3 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 5 } + }; + + public static TheoryData, Func> PredicatePredicateSingle => + new() + { + { new[] { 1 }, _ => true, _ => true }, + + { new[] { 1, 2, 3, 4, 5 }, item => item == 3, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, _ => true, item => item == 3 } + }; + + public static TheoryData, Func> SkipTakePredicatePredicateSingle => + new() + { + { new[] { 1 }, 0, 9, _ => true, _ => true }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 3, _ => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, item => item == 3 } + }; + + public static TheoryData> PredicateAtSingle => + new() + { + { new[] { 1 }, (_, __) => true }, + { new[] { 1 }, (item, _) => item == 1 }, + { new[] { 1 }, (_, index) => index == 0 }, + + { new[] { 1, 2, 3, 4, 5 }, (item, _) => item == 1 }, + { new[] { 1, 2, 3, 4, 5 }, (item, _) => item == 3 }, + { new[] { 1, 2, 3, 4, 5 }, (item, _) => item == 5 }, + { new[] { 1, 2, 3, 4, 5 }, (_, index) => index == 0 }, + { new[] { 1, 2, 3, 4, 5 }, (_, index) => index == 2 }, + { new[] { 1, 2, 3, 4, 5 }, (_, index) => index == 4 } + }; + + public static TheoryData> SkipTakePredicateAtSingle => + new() + { + { new[] { 1 }, -1, 1, (_, __) => true }, + { new[] { 1 }, 0, 1, (_, __) => true }, + { new[] { 1 }, 0, 1, (item, _) => item == 1 }, + { new[] { 1 }, 0, 1, (_, index) => index == 0 }, + + { new[] { 1 }, -1, 9, (_, __) => true }, + { new[] { 1 }, 0, 9, (_, __) => true }, + { new[] { 1 }, 0, 9, (item, _) => item == 1 }, + { new[] { 1 }, 0, 9, (_, index) => index == 0 }, + + { new[] { 1, 2, 3, 4, 5 }, -1, 1, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 1, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 2, 1, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 4, 1, (_, __) => true }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (item, _) => item == 1 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (item, _) => item == 3 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (item, _) => item == 5 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (_, index) => index == 0 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (_, index) => index == 2 }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, (_, index) => index == 4 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, (_, index) => index == 0 }, + { new[] { 1, 2, 3, 4, 5 }, 2, 9, (_, index) => index == 2 } + }; + + public static TheoryData> SelectorSingle => + new() + { + { new[] { 1 }, item => item.ToString() } + }; + + public static TheoryData> SkipTakeSelectorSingle => + new() + { + { new[] { 1 }, 0, 1, item => item.ToString() }, + + { new[] { 1 }, -1, 9, item => item.ToString() }, + { new[] { 1 }, 0, 9, item => item.ToString() }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 1, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 2, 1, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 4, 1, item => item.ToString() } + }; + + public static TheoryData> SelectorAtSingle => + new() + { + { new[] { 1 }, (item, index) => $"{item} {index}" } + }; + + public static TheoryData> SkipTakeSelectorAtSingle => + new() + { + { new[] { 1 }, -1, 1, (item, index) => $"{item} {index}" }, + { new[] { 1 }, 0, 1, (item, index) => $"{item} {index}" }, + + { new[] { 1 }, -1, 9, (item, index) => $"{item} {index}" }, + { new[] { 1 }, 0, 9, (item, index) => $"{item} {index}" }, + + { new[] { 1, 2, 3, 4, 5 }, 0, 1, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, 2, 1, (item, index) => $"{item} {index}" }, + { new[] { 1, 2, 3, 4, 5 }, 4, 1, (item, index) => $"{item} {index}" } + }; + + public static TheoryData, Func> PredicateSelectorSingle => + new() + { + { new[] { 1 }, _ => true, item => item.ToString() }, + { new[] { 1 }, item => item == 1, item => item.ToString() }, + + { new[] { 1, 2, 3, 4, 5 }, item => item == 1, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, item => item == 3, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, item => item == 5, item => item.ToString() } + }; + + public static TheoryData, Func> SkipTakePredicateSelectorSingle => + new() + { + { new[] { 1 }, -1, 1, _ => true, item => item.ToString() }, + { new[] { 1 }, 0, 1, _ => true, item => item.ToString() }, + { new[] { 1 }, 0, 1, item => item == 1, item => item.ToString() }, + + { new[] { 1 }, -1, 9, _ => true, item => item.ToString() }, + { new[] { 1 }, 0, 9, _ => true, item => item.ToString() }, + { new[] { 1 }, 0, 9, item => item == 1, item => item.ToString() }, + + { new[] { 1, 2, 3, 4, 5 }, -1, 1, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 1, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 2, 1, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 4, 1, _ => true, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 1, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 3, item => item.ToString() }, + { new[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 5, item => item.ToString() } + }; + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/DelegateExtensions.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/DelegateExtensions.cs similarity index 100% rename from NetFabric.Hyperlinq.UnitTests/Utils/DelegateExtensions.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/DelegateExtensions.cs diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Utils/SpanExtensions.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/SpanExtensions.cs new file mode 100644 index 000000000..b2c8dcd37 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/SpanExtensions.cs @@ -0,0 +1,63 @@ +using System; +using System.Buffers; +using System.Collections.Generic; + +namespace NetFabric.Hyperlinq.UnitTests +{ + static class SpanExtensions + { + public static bool SequenceEqual(this IMemoryOwner first, IEnumerable second, IEqualityComparer? comparer = default) + => SequenceEqual((ReadOnlySpan)first.Memory.Span, second, comparer); + + public static bool SequenceEqual(this Memory first, IEnumerable second, IEqualityComparer? comparer = default) + => SequenceEqual((ReadOnlySpan)first.Span, second, comparer); + + public static bool SequenceEqual(this ReadOnlyMemory first, IEnumerable second, IEqualityComparer? comparer = default) + => SequenceEqual(first.Span, second, comparer); + + public static bool SequenceEqual(this Span first, IEnumerable second, IEqualityComparer? comparer = default) + => SequenceEqual((ReadOnlySpan)first, second, comparer); + + public static bool SequenceEqual(this ReadOnlySpan first, IEnumerable second, IEqualityComparer? comparer = default) + { + if (Utils.IsValueType() && comparer.UseDefaultComparer()) + { + using var enumerator = second.GetEnumerator(); + for (var index = 0; true; index++) + { + var resultEnded = index == first.Length; + var expectedEnded = !enumerator.MoveNext(); + + if (resultEnded != expectedEnded) + return false; + + if (resultEnded) + return true; + + if (!EqualityComparer.Default.Equals(first[index], enumerator.Current)) + return false; + } + } + else + { + comparer ??= EqualityComparer.Default; + + using var enumerator = second.GetEnumerator(); + for (var index = 0; true; index++) + { + var resultEnded = index == first.Length; + var expectedEnded = !enumerator.MoveNext(); + + if (resultEnded != expectedEnded) + return false; + + if (resultEnded) + return true; + + if (!comparer.Equals(first[index], enumerator.Current)) + return false; + } + } + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Utils/TestComparer.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/TestComparer.cs new file mode 100644 index 000000000..8bfa97648 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/TestComparer.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace NetFabric.Hyperlinq.UnitTests +{ + class TestComparer : IEqualityComparer + { + public int EqualsCounter { get; private set; } + public int GetHashCodeCounter { get; private set; } + + public bool Equals(T? x, T? y) + { + EqualsCounter++; + return EqualityComparer.Default.Equals(x, y); + } + + public int GetHashCode([DisallowNull] T obj) + { + GetHashCodeCounter++; + return EqualityComparer.Default.GetHashCode(obj); + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsAsyncEnumerable.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsAsyncEnumerable.cs new file mode 100644 index 000000000..027b9b9ad --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsAsyncEnumerable.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace NetFabric.Hyperlinq +{ + public static partial class Wrap + { + public static AsyncEnumerableWrapper AsAsyncEnumerable(T[] source) + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + // ReSharper disable once HeapView.ObjectAllocation.Evident + _ => new AsyncEnumerableWrapper(source) + }; + + public class AsyncEnumerableWrapper + : IAsyncEnumerable + { + readonly T[] source; + + internal AsyncEnumerableWrapper(T[] source) + => this.source = source; + + public AsyncEnumerator GetAsyncEnumerator() + => new(source); + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken _) + // ReSharper disable once HeapView.BoxingAllocation + => new AsyncEnumerator(source); + + public readonly struct GetAsyncEnumeratorFunction + : IFunction, CancellationToken, AsyncEnumerator> + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public AsyncEnumerator Invoke(AsyncEnumerableWrapper enumerable, CancellationToken _) + => enumerable.GetAsyncEnumerator(); + } + } + } +} diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsAsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsAsyncValueEnumerable.cs new file mode 100644 index 000000000..08841b05f --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsAsyncValueEnumerable.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace NetFabric.Hyperlinq +{ + public static partial class Wrap + { + public static AsyncValueEnumerableWrapper AsAsyncValueEnumerable(T[] source) + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + _ => new AsyncValueEnumerableWrapper(source) + }; + + public readonly struct AsyncValueEnumerableWrapper + : IAsyncValueEnumerable> + { + readonly T[] source; + + internal AsyncValueEnumerableWrapper(T[] source) + => this.source = source; + + public AsyncEnumerator GetAsyncEnumerator() + => new(source); + + AsyncEnumerator IAsyncValueEnumerable>.GetAsyncEnumerator(CancellationToken _) + => new(source); + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken _) + // ReSharper disable once HeapView.BoxingAllocation + => new AsyncEnumerator(source); + + public readonly struct GetAsyncEnumeratorFunction + : IFunction, CancellationToken, AsyncEnumerator> + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public AsyncEnumerator Invoke(AsyncValueEnumerableWrapper enumerable, CancellationToken _) + => enumerable.GetAsyncEnumerator(); + } + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsCollection.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsCollection.cs similarity index 62% rename from NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsCollection.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsCollection.cs index 35c83b075..b9ebad3f9 100644 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsCollection.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsCollection.cs @@ -1,15 +1,19 @@ using System; using System.Collections; using System.Collections.Generic; +using Xunit.Sdk; namespace NetFabric.Hyperlinq { public static partial class Wrap { public static CollectionWrapper AsCollection(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + // ReSharper disable once HeapView.ObjectAllocation.Evident + _ => new CollectionWrapper(source) + }; public class CollectionWrapper : ReadOnlyCollectionWrapper @@ -19,14 +23,14 @@ internal CollectionWrapper(T[] source) : base(source) { } - public bool IsReadOnly + bool ICollection.IsReadOnly => true; - public void CopyTo(T[] array, int arrayIndex) + void ICollection.CopyTo(T[] array, int arrayIndex) => source.CopyTo(array, arrayIndex); - public bool Contains(T item) - => ((IList)source).Contains(item); + bool ICollection.Contains(T item) + => ((ICollection)source).Contains(item); void ICollection.Add(T item) => throw new NotSupportedException(); diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsEnumerable.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsEnumerable.cs new file mode 100644 index 000000000..bb738371e --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsEnumerable.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class Wrap + { + public static EnumerableWrapper AsEnumerable(T[] source) + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + // ReSharper disable once HeapView.ObjectAllocation.Evident + _ => new EnumerableWrapper(source) + }; + + public class EnumerableWrapper + : IEnumerable + { + protected readonly T[] source; + + internal EnumerableWrapper(T[] source) + => this.source = source; + + public Enumerator GetEnumerator() + => new(source); + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + + public readonly struct GetEnumeratorFunction + : IFunction, Enumerator> + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator Invoke(EnumerableWrapper enumerable) + => enumerable.GetEnumerator(); + } + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsFunctionIn.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsFunctionIn.cs similarity index 100% rename from NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsFunctionIn.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsFunctionIn.cs diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsList.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsList.cs similarity index 81% rename from NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsList.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsList.cs index 9b6d8fdc5..5ee461a57 100644 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsList.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsList.cs @@ -7,9 +7,12 @@ namespace NetFabric.Hyperlinq public static partial class Wrap { public static ListWrapper AsList(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + // ReSharper disable once HeapView.ObjectAllocation.Evident + _ => new ListWrapper(source) + }; public class ListWrapper : ReadOnlyListWrapper @@ -31,7 +34,7 @@ public void CopyTo(T[] array, int arrayIndex) => source.CopyTo(array, arrayIndex); public bool Contains(T item) - => ((IList)source).Contains(item); + => ((ICollection)source).Contains(item); public int IndexOf(T item) => ((IList)source).IndexOf(item); diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyCollection.cs similarity index 67% rename from NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyCollection.cs index 6c6762bc4..bcb16a3ed 100644 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyCollection.cs @@ -7,9 +7,12 @@ namespace NetFabric.Hyperlinq public static partial class Wrap { public static ReadOnlyCollectionWrapper AsReadOnlyCollection(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + // ReSharper disable once HeapView.ObjectAllocation.Evident + _ => new ReadOnlyCollectionWrapper(source) + }; public class ReadOnlyCollectionWrapper : EnumerableWrapper diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyList.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyList.cs similarity index 67% rename from NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyList.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyList.cs index f7e7b019e..1948c72dd 100644 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyList.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsReadOnlyList.cs @@ -7,9 +7,12 @@ namespace NetFabric.Hyperlinq public static partial class Wrap { public static ReadOnlyListWrapper AsReadOnlyList(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + // ReSharper disable once HeapView.ObjectAllocation.Evident + _ => new ReadOnlyListWrapper(source) + }; public class ReadOnlyListWrapper : ReadOnlyCollectionWrapper diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueCollection.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueCollection.cs similarity index 62% rename from NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueCollection.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueCollection.cs index 948033e83..05cdb1dcd 100644 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueCollection.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueCollection.cs @@ -1,15 +1,18 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { public static partial class Wrap { public static ValueCollectionWrapper AsValueCollection(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + _ => new ValueCollectionWrapper(source) + }; public readonly struct ValueCollectionWrapper : IValueReadOnlyCollection> @@ -20,15 +23,19 @@ public static ValueCollectionWrapper AsValueCollection(T[] source) internal ValueCollectionWrapper(T[] source) => this.source = source; - public readonly int Count + public int Count => source.Length; - public readonly Enumerator GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); + public Enumerator GetEnumerator() + => new(source); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); public bool IsReadOnly => true; diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueEnumerable.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueEnumerable.cs new file mode 100644 index 000000000..63dff6ba2 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueEnumerable.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class Wrap + { + public static ValueEnumerableWrapper AsValueEnumerable(T[] source) + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + _ => new ValueEnumerableWrapper(source) + }; + + public readonly struct ValueEnumerableWrapper + : IValueEnumerable> + { + readonly T[] source; + + internal ValueEnumerableWrapper(T[] source) + => this.source = source; + + public Enumerator GetEnumerator() + => new(source); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + + public readonly struct GetEnumeratorFunction + : IFunction, Enumerator> + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator Invoke(ValueEnumerableWrapper enumerable) + => enumerable.GetEnumerator(); + } + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueList.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueList.cs similarity index 69% rename from NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueList.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueList.cs index f731165b2..4033031c9 100644 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueList.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueList.cs @@ -1,15 +1,18 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { public static partial class Wrap { public static ValueListWrapper AsValueList(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + _ => new ValueListWrapper(source) + }; public readonly struct ValueListWrapper : IValueReadOnlyList> @@ -20,10 +23,10 @@ public static ValueListWrapper AsValueList(T[] source) internal ValueListWrapper(T[] source) => this.source = source; - public readonly int Count + public int Count => source.Length; - public readonly T this[int index] + public T this[int index] => source[index]; T IList.this[int index] @@ -32,12 +35,16 @@ internal ValueListWrapper(T[] source) set => throw new NotSupportedException(); } - public readonly Enumerator GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); + public Enumerator GetEnumerator() + => new(source); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); public bool IsReadOnly => true; diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyCollection.cs new file mode 100644 index 000000000..8128eead9 --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyCollection.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class Wrap + { + public static ValueReadOnlyCollectionWrapper AsValueReadOnlyCollection(T[] source) + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + _ => new ValueReadOnlyCollectionWrapper(source) + }; + + public readonly struct ValueReadOnlyCollectionWrapper + : IValueReadOnlyCollection> + { + readonly T[] source; + + internal ValueReadOnlyCollectionWrapper(T[] source) + => this.source = source; + + public int Count + => source.Length; + + public Enumerator GetEnumerator() + => new(source); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyList.cs new file mode 100644 index 000000000..f4b6c386c --- /dev/null +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyList.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class Wrap + { + public static ValueReadOnlyListWrapper AsValueReadOnlyList(T[] source) + => source switch + { + null => throw new ArgumentNullException(nameof(source)), + _ => new ValueReadOnlyListWrapper(source) + }; + + public readonly struct ValueReadOnlyListWrapper + : IValueReadOnlyList> + { + readonly T[] source; + + internal ValueReadOnlyListWrapper(T[] source) + => this.source = source; + + public int Count + => source.Length; + + public T this[int index] + => source[index]; + + public Enumerator GetEnumerator() + => new(source); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsyncEnumerator.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsyncEnumerator.cs similarity index 72% rename from NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsyncEnumerator.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsyncEnumerator.cs index 2ead5fcf6..0b9b6834a 100644 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsyncEnumerator.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.AsyncEnumerator.cs @@ -20,10 +20,15 @@ internal AsyncEnumerator(T[] source) } public readonly T Current - => source[index]; + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask MoveNextAsync() - => new ValueTask(++index < source.Length); + => new(++index < source.Length); + public readonly ValueTask DisposeAsync() => default; } diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.Enumerator.cs b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.Enumerator.cs similarity index 66% rename from NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.Enumerator.cs rename to NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.Enumerator.cs index 4d944d7a8..09c670e6f 100644 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.Enumerator.cs +++ b/NetFabric.Hyperlinq.Core.UnitTests/Utils/Wrappers/Wrap.Enumerator.cs @@ -19,11 +19,16 @@ internal Enumerator(T[] source) index = -1; } - public readonly T Current - => source[index]; - readonly object IEnumerator.Current + public readonly T Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation => source[index]; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() => ++index < source.Length; public void Reset() diff --git a/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ReadOnlySpan.cs new file mode 100644 index 000000000..f2470d7bf --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ReadOnlySpan.cs @@ -0,0 +1,44 @@ +using System; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(ReadOnlySpan source) + => source.Length; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(ReadOnlySpan source, Func predicate) + => source.Count(new FunctionWrapper(predicate)); + + public static int Count(this ReadOnlySpan source, TPredicate predicate = default) + where TPredicate: struct, IFunction + { + var counter = 0; + foreach (var item in source) + { + counter += predicate.Invoke(item).AsByte(); + } + return counter; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(this ReadOnlySpan source, Func predicate) + => source.CountAt(new FunctionWrapper(predicate)); + + public static int CountAt(this ReadOnlySpan source, TPredicate predicate = default) + where TPredicate: struct, IFunction + { + var counter = 0; + for (var index = 0; index < source.Length; index++) + { + var item = source[index]; + counter += predicate.Invoke(item, index).AsByte(); + } + return counter; + } + } +} + diff --git a/NetFabric.Hyperlinq/Aggregation/Count/Count.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ValueEnumerable.cs similarity index 83% rename from NetFabric.Hyperlinq/Aggregation/Count/Count.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ValueEnumerable.cs index 5a44adece..4e033636d 100644 --- a/NetFabric.Hyperlinq/Aggregation/Count/Count.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ValueEnumerable.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { @@ -18,8 +19,8 @@ public static partial class ValueEnumerableExtensions } return counter; } - - internal static int Count(this TEnumerable source, TPredicate predicate) + + public static int Count(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate: struct, IFunction @@ -34,7 +35,7 @@ public static partial class ValueEnumerableExtensions return counter; } - internal static int CountAt(this TEnumerable source, TPredicate predicate) + public static int CountAt(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate: struct, IFunction diff --git a/NetFabric.Hyperlinq/Aggregation/Count/Count.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ValueReadOnlyCollection.cs similarity index 76% rename from NetFabric.Hyperlinq/Aggregation/Count/Count.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ValueReadOnlyCollection.cs index d8bcbaf2b..6481d6078 100644 --- a/NetFabric.Hyperlinq/Aggregation/Count/Count.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ValueReadOnlyCollection.cs @@ -1,15 +1,18 @@ +using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { public static partial class ValueReadOnlyCollectionExtensions { + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Count(this TEnumerable source) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator => source.Count; - static int Count(this TEnumerable source, TPredicate predicate) + public static int Count(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator where TPredicate: struct, IFunction @@ -19,7 +22,7 @@ public static partial class ValueReadOnlyCollectionExtensions _ => ValueEnumerableExtensions.Count(source, predicate) }; - static int CountAt(this TEnumerable source, TPredicate predicate) + public static int CountAt(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator where TPredicate: struct, IFunction diff --git a/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ValueReadOnlyList.cs new file mode 100644 index 000000000..11f843b7c --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Aggregation/Count/Count.ValueReadOnlyList.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(this TEnumerable source) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.Count(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(this TEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TPredicate: struct, IFunction + => ValueReadOnlyCollectionExtensions.Count(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountAt(this TEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TPredicate: struct, IFunction + => ValueReadOnlyCollectionExtensions.CountAt(source, predicate); + + } +} + diff --git a/NetFabric.Hyperlinq/Aggregation/Count/CountAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Aggregation/Count/CountAsync.AsyncValueEnumerable.cs similarity index 85% rename from NetFabric.Hyperlinq/Aggregation/Count/CountAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Aggregation/Count/CountAsync.AsyncValueEnumerable.cs index c424480b6..efa84676e 100644 --- a/NetFabric.Hyperlinq/Aggregation/Count/CountAsync.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Aggregation/Count/CountAsync.AsyncValueEnumerable.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -28,7 +29,7 @@ public static partial class AsyncValueEnumerableExtensions return counter; } - static async ValueTask CountAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + public static async ValueTask CountAsync(this TEnumerable source, TPredicate predicate = default, CancellationToken cancellationToken = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate: struct, IAsyncFunction @@ -53,7 +54,7 @@ public static partial class AsyncValueEnumerableExtensions return counter; } - static async ValueTask CountAtAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + public static async ValueTask CountAtAsync(this TEnumerable source, TPredicate predicate = default, CancellationToken cancellationToken = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate: struct, IAsyncFunction diff --git a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.Range.cs b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.Range.cs similarity index 90% rename from NetFabric.Hyperlinq/Aggregation/Sum/Sum.Range.cs rename to NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.Range.cs index c67621338..3ca8d9949 100644 --- a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.Range.cs +++ b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.Range.cs @@ -43,18 +43,18 @@ static int SumRange(int start, int count) } for (index = 0; index < Vector.Count; index++) - sum = GenericsOperator.Add(vectorSum[index], sum); + sum = Scalar.Add(vectorSum[index], sum); } if (start is 0) { for (; index < count; index++) - sum = GenericsOperator.Add(selector.Invoke(index), sum); + sum = Scalar.Add(selector.Invoke(index), sum); } else { for (; index < count; index++) - sum = GenericsOperator.Add(selector.Invoke(index + start), sum); + sum = Scalar.Add(selector.Invoke(index + start), sum); } return sum; diff --git a/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ReadOnlySpan.cs new file mode 100644 index 000000000..d3e87fe90 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ReadOnlySpan.cs @@ -0,0 +1,183 @@ +using System; +using System.Numerics; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + + static TSum Sum(this ReadOnlySpan source) + where TSum : struct + { + var sum0 = default(TSum); + var sum1 = default(TSum); + for (var index = 0; index < source.Length - 1; index += 2) + { + var item0 = source[index]; + var item1 = source[index + 1]; + sum0 = Scalar.Add(item0, sum0); + sum1 = Scalar.Add(item1, sum1); + } + + if (source.Length.IsOdd()) + sum0 = Scalar.Add(source[source.Length - 1], sum0); + + return Scalar.Add(sum0, sum1); + } + + + static TSum SumVector(this ReadOnlySpan source) + where TSource : struct + where TSum : struct + { + if (!Vector.IsHardwareAccelerated || source.Length <= Vector.Count * 2) + return Sum(source); + + var vectors = MemoryMarshal.Cast>(source); + var vectorSum = Vector.Zero; + + foreach (var vector in vectors) + vectorSum += vector; + + var count = source.Length % Vector.Count; + return Scalar.Add(vectorSum.Sum(), Sum(source.Slice(source.Length - count, count))); + } + + + static TSum Sum(this ReadOnlySpan source, TPredicate predicate) + where TPredicate : struct, IFunction + where TSum : struct + { + var sum0 = default(TSum); + var sum1 = default(TSum); + for (var index = 0; index < source.Length - 1; index += 2) + { + var item0 = source[index]; + var item1 = source[index + 1]; + sum0 = Scalar.Add(Scalar.GetValueOrDefault(predicate, item0), sum0); + sum1 = Scalar.Add(Scalar.GetValueOrDefault(predicate, item1), sum1); + } + if (source.Length.IsOdd()) + { + var item = source[source.Length - 1]; + sum0 = Scalar.Add(Scalar.GetValueOrDefault(predicate, item), sum0); + } + return Scalar.Add(sum0, sum1); + } + + + static TSum SumAt(this ReadOnlySpan source, TPredicate predicate) + where TPredicate : struct, IFunction + where TSum : struct + { + var sum0 = default(TSum); + var sum1 = default(TSum); + for (var index = 0; index < source.Length - 1; index += 2) + { + var item0 = source[index]; + var item1 = source[index + 1]; + sum0 = Scalar.Add(Scalar.GetValueOrDefault(predicate, item0, index), sum0); + sum1 = Scalar.Add(Scalar.GetValueOrDefault(predicate, item1, index + 1), sum1); + } + if (source.Length.IsOdd()) + { + var index = source.Length - 1; + var item = source[index]; + sum0 = Scalar.Add(Scalar.GetValueOrDefault(predicate, item, index), sum0); + } + return Scalar.Add(sum0, sum1); + } + + + static TSum Sum(this ReadOnlySpan source, TSelector selector) + where TSelector : struct, IFunction + where TSum : struct + { + var sum0 = default(TSum); + var sum1 = default(TSum); + for (var index = 0; index < source.Length - 1; index += 2) + { + var item0 = source[index]; + var item1 = source[index + 1]; + sum0 = Scalar.Add(selector.Invoke(item0), sum0); + sum1 = Scalar.Add(selector.Invoke(item1), sum1); + } + + if (source.Length.IsOdd()) + sum0 = Scalar.Add(selector.Invoke(source[source.Length - 1]), sum0); + + return Scalar.Add(sum0, sum1); + } + + + static TSum SumVector(this ReadOnlySpan source, TVectorSelector vectorSelector, TSelector selector) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + where TSource : struct + where TResult : struct + where TSum : struct + { + if (!Vector.IsHardwareAccelerated || source.Length <= Vector.Count * 2) + return Sum(source); + + var vectors = MemoryMarshal.Cast>(source); + var vectorSum = Vector.Zero; + + foreach (var vector in vectors) + vectorSum += vectorSelector.Invoke(vector); + + var count = source.Length % Vector.Count; + return Scalar.Add(vectorSum.Sum(), Sum(source.Slice(source.Length - count, count), selector)); + } + + + static TSum SumAt(this ReadOnlySpan source, TSelector selector) + where TSelector : struct, IFunction + where TSum : struct + { + var sum0 = default(TSum); + var sum1 = default(TSum); + for (var index = 0; index < source.Length - 1; index += 2) + { + var item0 = source[index]; + var item1 = source[index + 1]; + sum0 = Scalar.Add(selector.Invoke(item0, index), sum0); + sum1 = Scalar.Add(selector.Invoke(item1, index + 1), sum1); + } + if (source.Length.IsOdd()) + { + var index = source.Length - 1; + sum0 = Scalar.Add(selector.Invoke(source[index], index), sum0); + } + return Scalar.Add(sum0, sum1); + } + + + static TSum Sum(this ReadOnlySpan source, TPredicate predicate, TSelector selector) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + where TSum : struct + { + var sum0 = default(TSum); + var sum1 = default(TSum); + for (var index = 0; index < source.Length - 1; index += 2) + { + var item0 = source[index]; + var item1 = source[index + 1]; + if (predicate.Invoke(item0)) + sum0 = Scalar.Add(selector.Invoke(item0), sum0); + if (predicate.Invoke(item1)) + sum1 = Scalar.Add(selector.Invoke(item1), sum1); + } + if (source.Length.IsOdd()) + { + var item = source[source.Length - 1]; + if (predicate.Invoke(item)) + sum0 = Scalar.Add(selector.Invoke(item), sum0); + } + return Scalar.Add(sum0, sum1); + } + } +} + diff --git a/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ValueEnumerable.cs new file mode 100644 index 000000000..29ab70c16 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ValueEnumerable.cs @@ -0,0 +1,108 @@ +using System.Collections.Generic; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueEnumerableExtensions + { + + public static TSum Sum(this TEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSum : struct + { + var sum = default(TSum); + using var enumerator = source.GetEnumerator(); + while (enumerator.MoveNext()) + sum = Scalar.Add(enumerator.Current, sum); + return sum; + } + + + internal static TSum Sum(this TEnumerable source, TPredicate predicate) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSum : struct + { + var sum = default(TSum); + using var enumerator = source.GetEnumerator(); + while (enumerator.MoveNext()) + { + var item = enumerator.Current; + sum = Scalar.Add(Scalar.GetValueOrDefault(predicate, item), sum); + } + return sum; + } + + + internal static TSum SumAt(this TEnumerable source, TPredicate predicate) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSum : struct + { + var sum = default(TSum); + using var enumerator = source.GetEnumerator(); + for (var index = 0; enumerator.MoveNext(); index++) + { + var item = enumerator.Current; + sum = Scalar.Add(Scalar.GetValueOrDefault(predicate, item, index), sum); + } + return sum; + } + + + internal static TSum Sum(this TEnumerable source, TSelector selector) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TSum : struct + { + var sum = default(TSum); + using var enumerator = source.GetEnumerator(); + while (enumerator.MoveNext()) + { + var item = enumerator.Current; + sum = Scalar.Add(selector.Invoke(item), sum); + } + return sum; + } + + + internal static TSum SumAt(this TEnumerable source, TSelector selector) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TSum : struct + { + var sum = default(TSum); + using var enumerator = source.GetEnumerator(); + for (var index = 0; enumerator.MoveNext(); index++) + { + var item = enumerator.Current; + sum = Scalar.Add(selector.Invoke(item, index), sum); + } + return sum; + } + + + internal static TSum Sum(this TEnumerable source, TPredicate predicate, TSelector selector) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + where TSum : struct + { + var sum = default(TSum); + using var enumerator = source.GetEnumerator(); + while (enumerator.MoveNext()) + { + var item = enumerator.Current; + if (predicate.Invoke(item)) + sum = Scalar.Add(selector.Invoke(item), sum); + } + return sum; + } + } +} + diff --git a/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ValueReadOnlyCollection.cs new file mode 100644 index 000000000..18b1702ee --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ValueReadOnlyCollection.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyCollectionExtensions + { + + public static TSum Sum(this TEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSum : struct + => source switch + { + {Count: 0} => default, + _ => ValueEnumerableExtensions.Sum(source) + }; + + + static TSum Sum(this TEnumerable source, TPredicate predicate) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate: struct, IFunction + where TSum : struct + => source switch + { + {Count: 0} => default, + _ => ValueEnumerableExtensions.Sum(source, predicate) + }; + + + static TSum SumAt(this TEnumerable source, TPredicate predicate) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate: struct, IFunction + where TSum : struct + => source switch + { + {Count: 0} => default, + _ => ValueEnumerableExtensions.SumAt(source, predicate) + }; + + + internal static TSum Sum(this TEnumerable source, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector: struct, IFunction + where TSum : struct + => source switch + { + {Count: 0} => default, + _ => ValueEnumerableExtensions.Sum(source, selector) + }; + + + internal static TSum SumAt(this TEnumerable source, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TSum : struct + => source switch + { + {Count: 0} => default, + _ => ValueEnumerableExtensions.SumAt(source, selector) + }; + + + static TSum Sum(this TEnumerable source, TPredicate predicate, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate: struct, IFunction + where TSelector: struct, IFunction + where TSum : struct + => source switch + { + {Count: 0} => default, + _ => ValueEnumerableExtensions.Sum(source, predicate, selector) + }; + + } +} + diff --git a/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ValueReadOnlyList.cs new file mode 100644 index 000000000..3df49ac22 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Aggregation/Sum/Sum.ValueReadOnlyList.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TSum Sum(this TEnumerable source) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSum : struct + => ValueReadOnlyCollectionExtensions.Sum(source); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Aggregation/Sum/SumAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Aggregation/Sum/SumAsync.AsyncValueEnumerable.cs new file mode 100644 index 000000000..442427cd2 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Aggregation/Sum/SumAsync.AsyncValueEnumerable.cs @@ -0,0 +1,154 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace NetFabric.Hyperlinq +{ + public static partial class AsyncValueEnumerableExtensions + { + + public static async ValueTask SumAsync(this TEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSum : struct + { + var sum = default(TSum); + var enumerator = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await enumerator.MoveNextAsync().ConfigureAwait(false)) + sum = Scalar.Add(enumerator.Current, sum); + } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } + return sum; + } + + + internal static async ValueTask SumAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSum : struct + { + var sum = default(TSum); + var enumerator = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await enumerator.MoveNextAsync().ConfigureAwait(false)) + { + var item = enumerator.Current; + if (await predicate.InvokeAsync(item, cancellationToken).ConfigureAwait(false)) + sum = Scalar.Add(item, sum); + } + } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } + return sum; + } + + + internal static async ValueTask SumAtAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSum : struct + { + var sum = default(TSum); + var enumerator = source.GetAsyncEnumerator(cancellationToken); + try + { + for (var index = 0; await enumerator.MoveNextAsync().ConfigureAwait(false); index++) + { + var item = enumerator.Current; + if (await predicate.InvokeAsync(item, index, cancellationToken).ConfigureAwait(false)) + sum = Scalar.Add(item, sum); + } + } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } + return sum; + } + + + internal static async ValueTask SumAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + where TSum : struct + { + var sum = default(TSum); + var enumerator = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await enumerator.MoveNextAsync().ConfigureAwait(false)) + { + var item = enumerator.Current; + sum = Scalar.Add(await selector.InvokeAsync(item, cancellationToken).ConfigureAwait(false), sum); + } + } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } + return sum; + } + + + internal static async ValueTask SumAtAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + where TSum : struct + { + var sum = default(TSum); + var enumerator = source.GetAsyncEnumerator(cancellationToken); + try + { + for (var index = 0; await enumerator.MoveNextAsync().ConfigureAwait(false); index++) + { + var item = enumerator.Current; + sum = Scalar.Add(await selector.InvokeAsync(item, index, cancellationToken).ConfigureAwait(false), sum); + } + } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } + return sum; + } + + + internal static async ValueTask SumAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate, TSelector selector) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + where TSum : struct + { + var sum = default(TSum); + var enumerator = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await enumerator.MoveNextAsync().ConfigureAwait(false)) + { + var item = enumerator.Current; + if (await predicate.InvokeAsync(item, cancellationToken).ConfigureAwait(false)) + sum = Scalar.Add(await selector.InvokeAsync(item, cancellationToken).ConfigureAwait(false), sum); + } + } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } + return sum; + } + } +} + diff --git a/NetFabric.Hyperlinq/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.cs similarity index 100% rename from NetFabric.Hyperlinq/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Conversion/AsAsyncEnumerable/AsAsyncEnumerable.AsyncValueEnumerable.cs diff --git a/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncEnumerable.cs new file mode 100644 index 000000000..67530fdac --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncEnumerable.cs @@ -0,0 +1,137 @@ +using System.Buffers; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +namespace NetFabric.Hyperlinq +{ + public static partial class AsyncEnumerableExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable AsAsyncValueEnumerable(this IAsyncEnumerable source) + => new(source); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct AsyncValueEnumerable + : IAsyncValueEnumerable.AsyncEnumerator> + { + readonly IAsyncEnumerable source; + + internal AsyncValueEnumerable(IAsyncEnumerable source) + => this.source = source; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public AsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + => new(source, cancellationToken); + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + // ReSharper disable once HeapView.BoxingAllocation + => new AsyncEnumerator(source, cancellationToken); + + public readonly struct AsyncEnumerator + : IAsyncEnumerator + { + readonly IAsyncEnumerator enumerator; + + internal AsyncEnumerator(IAsyncEnumerable enumerable, CancellationToken cancellationToken) + => enumerator = enumerable.GetAsyncEnumerator(cancellationToken); + + public TSource Current + => enumerator.Current; + + TSource IAsyncEnumerator.Current + => enumerator.Current; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask MoveNextAsync() + => enumerator.MoveNextAsync(); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask DisposeAsync() + => enumerator.DisposeAsync(); + } + + #region Conversion + + public AsyncValueEnumerable AsAsyncValueEnumerable() + => this; + + public IAsyncEnumerable AsAsyncEnumerable() + => source; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask ToArrayAsync() + => this.ToArrayAsync, AsyncEnumerator, TSource>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask> ToArrayAsync(ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) + => this.ToArrayAsync, AsyncEnumerator, TSource>(pool, cancellationToken, clearOnDispose); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask> ToListAsync() + => this.ToListAsync, AsyncEnumerator, TSource>(); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, int, int>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, int?, int>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, nint, nint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, nint?, nint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, nuint, nuint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, nuint?, nuint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, long, long>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, long?, long>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, float, float>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, float?, float>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, double, double>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, double?, double>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, decimal, decimal>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + => source.SumAsync, AsyncValueEnumerable.AsyncEnumerator, decimal?, decimal>(cancellationToken); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncValueEnumerable.cs new file mode 100644 index 000000000..b0b7bffb5 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'1.AsyncValueEnumerable.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +namespace NetFabric.Hyperlinq +{ + public static partial class AsyncValueEnumerableExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable AsAsyncValueEnumerable(this IAsyncValueEnumerable source) + where TEnumerator : struct, IAsyncEnumerator + => new(source); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct AsyncValueEnumerable + : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + { + readonly IAsyncValueEnumerable source; + + internal AsyncValueEnumerable(IAsyncValueEnumerable source) + => this.source = source; + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + => source.GetAsyncEnumerator(cancellationToken); + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + // ReSharper disable once HeapView.BoxingAllocation + => source.GetAsyncEnumerator(cancellationToken); + + #region Conversion + + public AsyncValueEnumerable AsAsyncValueEnumerable() + => this; + + public IAsyncEnumerable AsAsyncEnumerable() + => source; + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, int, int>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, int?, int>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, nint, nint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, nint?, nint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, nuint, nuint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, nuint?, nuint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, long, long>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, long?, long>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, float, float>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, float?, float>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, double, double>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, double?, double>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, decimal, decimal>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TEnumerator, decimal?, decimal>(cancellationToken); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncEnumerable.cs new file mode 100644 index 000000000..f418e35d8 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncEnumerable.cs @@ -0,0 +1,224 @@ +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +namespace NetFabric.Hyperlinq +{ + public static partial class AsyncEnumerableExtensions + { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable, FunctionWrapper> AsAsyncValueEnumerable(this TEnumerable source, Func getAsyncEnumerator) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + => AsAsyncValueEnumerable>(source, new FunctionWrapper(getAsyncEnumerator)); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable AsAsyncValueEnumerable(this TEnumerable source, TGetAsyncEnumerator getAsyncEnumerator = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TGetAsyncEnumerator : struct, IFunction + => new(source, getAsyncEnumerator, getAsyncEnumerator); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable, FunctionWrapper> AsAsyncValueEnumerable(this TEnumerable source, Func getAsyncEnumerator, Func getAsyncEnumerator2) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + => AsAsyncValueEnumerable, FunctionWrapper>(source, new FunctionWrapper(getAsyncEnumerator), new FunctionWrapper(getAsyncEnumerator2)); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable AsAsyncValueEnumerable(this TEnumerable source, TGetAsyncEnumerator getAsyncEnumerator = default, TGetAsyncEnumerator2 getAsyncEnumerator2 = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => new(source, getAsyncEnumerator, getAsyncEnumerator2); + + [StructLayout(LayoutKind.Auto)] + public partial struct AsyncValueEnumerable + : IAsyncValueEnumerable + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + { + readonly TEnumerable source; +#pragma warning disable IDE0044 // Add readonly modifier + TGetAsyncEnumerator getAsyncEnumerator; + TGetAsyncEnumerator2 getAsyncEnumerator2; +#pragma warning restore IDE0044 // Add readonly modifier + + internal AsyncValueEnumerable(TEnumerable source, TGetAsyncEnumerator getAsyncEnumerator, TGetAsyncEnumerator2 getAsyncEnumerator2) + => (this.source, this.getAsyncEnumerator, this.getAsyncEnumerator2) = (source, getAsyncEnumerator, getAsyncEnumerator2); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TEnumerator2 GetAsyncEnumerator(CancellationToken cancellationToken = default) + => getAsyncEnumerator2.Invoke(source, cancellationToken); + TEnumerator IAsyncValueEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + => getAsyncEnumerator.Invoke(source, cancellationToken); + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + // ReSharper disable once HeapView.PossibleBoxingAllocation + => source.GetAsyncEnumerator(cancellationToken); + + #region Conversion + + public AsyncValueEnumerable AsAsyncValueEnumerable() + => this; + + public TEnumerable AsAsyncEnumerable() + => source; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask ToArrayAsync() + => this.ToArrayAsync, TEnumerator, TSource>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask> ToArrayAsync(ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) + => this.ToArrayAsync, TEnumerator, TSource>(pool, cancellationToken, clearOnDispose); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask> ToListAsync() + => this.ToListAsync, TEnumerator, TSource>(); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, int, int>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, int?, int>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, nint, nint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, nint?, nint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, nuint, nuint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, nuint?, nuint>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, long, long>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, long?, long>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, float, float>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, float?, float>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, double, double>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, double?, double>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, decimal, decimal>(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.SumAsync, TEnumerator, decimal?, decimal>(cancellationToken); + } +} diff --git a/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncValueEnumerable.cs new file mode 100644 index 000000000..c54d790ba --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable'6.AsyncValueEnumerable.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +namespace NetFabric.Hyperlinq +{ + public static partial class AsyncValueEnumerableExtensions + { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable, FunctionWrapper> AsAsyncValueEnumerable(this TEnumerable source, Func getAsyncEnumerator) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => AsAsyncValueEnumerable>(source, new FunctionWrapper(getAsyncEnumerator)); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable AsAsyncValueEnumerable(this TEnumerable source, TGetAsyncEnumerator getAsyncEnumerator = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TGetAsyncEnumerator : struct, IFunction + => new(source, getAsyncEnumerator, getAsyncEnumerator); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable, FunctionWrapper> AsAsyncValueEnumerable(this TEnumerable source, Func getAsyncEnumerator, Func getAsyncEnumerator2) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + => AsAsyncValueEnumerable, FunctionWrapper>(source, new FunctionWrapper(getAsyncEnumerator), new FunctionWrapper(getAsyncEnumerator2)); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsyncValueEnumerable AsAsyncValueEnumerable(this TEnumerable source, TGetAsyncEnumerator getAsyncEnumerator = default, TGetAsyncEnumerator2 getAsyncEnumerator2 = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => new(source, getAsyncEnumerator, getAsyncEnumerator2); + + [StructLayout(LayoutKind.Auto)] + public partial struct AsyncValueEnumerable + : IAsyncValueEnumerable + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + { + internal readonly TEnumerable source; + internal TGetAsyncEnumerator getAsyncEnumerator; + internal TGetAsyncEnumerator2 getAsyncEnumerator2; + + internal AsyncValueEnumerable(TEnumerable source, TGetAsyncEnumerator getAsyncEnumerator, TGetAsyncEnumerator2 getAsyncEnumerator2) + => (this.source, this.getAsyncEnumerator, this.getAsyncEnumerator2) = (source, getAsyncEnumerator, getAsyncEnumerator2); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TEnumerator2 GetAsyncEnumerator(CancellationToken cancellationToken = default) + => getAsyncEnumerator2.Invoke(source, cancellationToken); + TEnumerator IAsyncValueEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + => getAsyncEnumerator.Invoke(source, cancellationToken); + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + // ReSharper disable once HeapView.PossibleBoxingAllocation + => source.GetAsyncEnumerator(cancellationToken); + + #region Conversion + + public AsyncValueEnumerable AsAsyncValueEnumerable() + => this; + + public TEnumerable AsAsyncEnumerable() + => source; + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this AsyncValueEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TEnumerator2 : struct + where TGetAsyncEnumerator : struct, IFunction + where TGetAsyncEnumerator2 : struct, IFunction + => source.source.SumAsync(cancellationToken); + } +} diff --git a/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsyncValueEnumerator.cs b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsyncValueEnumerator.cs new file mode 100644 index 000000000..9c63c511f --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/AsAsyncValueEnumerable/AsyncValueEnumerator.cs @@ -0,0 +1,35 @@ +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace NetFabric.Hyperlinq +{ + [StructLayout(LayoutKind.Auto)] + public readonly struct AsyncValueEnumerator + : IAsyncEnumerator + { + readonly IAsyncEnumerator enumerator; + + public AsyncValueEnumerator(IAsyncEnumerator enumerator) + => this.enumerator = enumerator; + + public TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => enumerator.Current; + } + TSource IAsyncEnumerator.Current + => enumerator.Current; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask MoveNextAsync() + => enumerator.MoveNextAsync(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask DisposeAsync() + => enumerator.DisposeAsync(); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsEnumerable/AsEnumerable.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/AsEnumerable/AsEnumerable.ValueEnumerable.cs similarity index 100% rename from NetFabric.Hyperlinq/Conversion/AsEnumerable/AsEnumerable.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Conversion/AsEnumerable/AsEnumerable.ValueEnumerable.cs diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.Array.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.Array.cs similarity index 100% rename from NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.Array.cs rename to NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.Array.cs diff --git a/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs new file mode 100644 index 000000000..c39e49457 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs @@ -0,0 +1,240 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ArraySegmentValueEnumerable AsValueEnumerable(this ArraySegment source) + => new(source); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct ArraySegmentValueEnumerable + : IValueReadOnlyList.DisposableEnumerator> + , IList + { + internal readonly ArraySegment source; + + internal ArraySegmentValueEnumerable(ArraySegment source) + => this.source = source; + + public int Count + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source.Count; + } + + public TSource this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + ThrowIfArgument.OutOfRange(index, Count, nameof(index)); + return source.Array![source.Offset + index]; + } + } + + TSource IList.this[int index] + { + get => this[index]; + + [ExcludeFromCodeCoverage] + // ReSharper disable once ValueParameterNotUsed + set => Throw.NotSupportedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SpanEnumerator GetEnumerator() + => new(source); + + DisposableEnumerator IValueEnumerable.GetEnumerator() + => new(source); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new DisposableEnumerator(source); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new DisposableEnumerator(source); + + + bool ICollection.IsReadOnly + => true; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(Span span) + => source.AsReadOnlySpan().CopyTo(span); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(TSource[] array, int arrayIndex) + => ((ICollection)source).CopyTo(array, arrayIndex); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(TSource item) + => ((ICollection)source).Contains(item); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int IndexOf(TSource item) + => ((IList)source).IndexOf(item); + + [ExcludeFromCodeCoverage] + void ICollection.Add(TSource item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + bool ICollection.Remove(TSource item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + void ICollection.Clear() + => Throw.NotSupportedException(); + + [ExcludeFromCodeCoverage] + void IList.Insert(int index, TSource item) + => Throw.NotSupportedException(); + + [ExcludeFromCodeCoverage] + void IList.RemoveAt(int index) + => Throw.NotSupportedException(); + + [StructLayout(LayoutKind.Auto)] + public struct DisposableEnumerator + : IEnumerator + { + readonly ArraySegment source; + int index; + + internal DisposableEnumerator(ArraySegment source) + { + this.source = source; + index = -1; + } + + public readonly TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source.Array![source.Offset + index]; + } + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => Current; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + => ++index < source.Count; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ExcludeFromCodeCoverage] + public void Reset() + => index = -1; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly void Dispose() { } + } + + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ArraySegmentValueEnumerable Skip(int count) + { + var (newOffset, newCount) = Utils.Skip(source.Count, count); + return new ArraySegmentValueEnumerable(new ArraySegment(source.Array!, source.Offset + newOffset, newCount)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ArraySegmentValueEnumerable Take(int count) + => new(new ArraySegment(source.Array!, source.Offset, Utils.Take(source.Count, count))); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this ArraySegmentValueEnumerable source) + => source.source.AsReadOnlySpan().Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsVector(this ArraySegmentValueEnumerable source, TSource value) + where TSource : struct + => source.source.AsReadOnlySpan().ContainsVector(value); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SpanSelectVectorContext, Vector>, FunctionWrapper> SelectVector(this ArraySegmentValueEnumerable source, Func, Vector> vectorSelector, Func selector) + where TSource : struct + where TResult : struct + => source.source.AsReadOnlySpan().SelectVector(vectorSelector, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SpanSelectVectorContext SelectVector(this ArraySegmentValueEnumerable source, TSelector selector = default) + where TSelector : struct, IFunction, Vector>, IFunction + where TSource : struct + where TResult : struct + => source.source.AsReadOnlySpan().SelectVector(selector, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SpanSelectVectorContext SelectVector(this ArraySegmentValueEnumerable source, TVectorSelector vectorSelector = default, TSelector selector = default) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + where TSource : struct + where TResult : struct + => source.source.AsReadOnlySpan().SelectVector(vectorSelector, selector); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ImmutableArray.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ImmutableArray.cs new file mode 100644 index 000000000..5304b8aed --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ImmutableArray.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Immutable; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static class ImmutableArrayExtensions + { + // Get the inner array and return its IValueEnumerable<> wrapper. + // Do not use the available AsSpan() or AsMemory() because the enumerables for ReadOnlySpan<> do not + // implement IEnumerable<>, restricting its use, and the enumerables for ReadOnlyMemory<> are less efficient + // because they call .Span in each iteration. + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ArrayExtensions.ArraySegmentValueEnumerable AsValueEnumerable(this ImmutableArray source) + => source.GetArray().AsValueEnumerable(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static TSource[] GetArray(this ImmutableArray source) + => Unsafe.As, TSource[]?>(ref source) ?? Array.Empty(); + } +} diff --git a/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.List.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.List.cs new file mode 100644 index 000000000..3531bba2d --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.List.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static class ListExtensions + { + // List is simply converted to ArraySegment and share its IValueEnumerable wrapper. + // It's not converted to ReadOnlySpan because its enumerables cannot be casted to IEnumerable, restricting its use. + // It's not converted to ReadOnlyMemory because it's less efficient in enumerables (it has to call .Span on each iteration). + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ArrayExtensions.ArraySegmentValueEnumerable AsValueEnumerable(this List source) + => source.AsArraySegment().AsValueEnumerable(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static ArraySegment AsArraySegment(this List source) + => new(source.GetItems(), 0, source.Count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static List AsList(this TSource[] source) + { + return source switch + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + { Length: 0 } => new List(), + _ => WrapArray(source) + }; + + static List WrapArray(TSource[] source) + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + var result = new List(); + var layout = Unsafe.As, ListLayout>(ref result); + layout.items = source; + layout.size = source.Length; + result.Capacity = source.Length; + return result; + } + } + + // ReSharper disable once ClassNeverInstantiated.Local + class ListLayout + { + public TSource[]? items; + +#if !NETCOREAPP3_0_OR_GREATER +#pragma warning disable IDE0051 // Remove unused private members +#pragma warning disable 169 + readonly object? syncRoot; +#pragma warning restore 169 +#pragma warning restore IDE0051 // Remove unused private members +#endif + public int size; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static TSource[] GetItems(this List source) + => Unsafe.As, ListLayout>(ref source).items + ?? Array.Empty(); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.Memory.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.Memory.cs similarity index 81% rename from NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.Memory.cs rename to NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.Memory.cs index 34330c106..7b25a3c4e 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.Memory.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.Memory.cs @@ -8,6 +8,6 @@ public static partial class ArrayExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static MemoryValueEnumerable AsValueEnumerable(this Memory source) - => ((ReadOnlyMemory)source).AsValueEnumerable(); + => source.AsReadOnlyMemory().AsValueEnumerable(); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs similarity index 62% rename from NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs rename to NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs index 5f2ef5481..d58c7cf91 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs @@ -1,5 +1,4 @@ using System; -using System.Buffers; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -12,11 +11,11 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static MemoryValueEnumerable AsValueEnumerable(this ReadOnlyMemory source) => new(source); - [GeneratorIgnore] [StructLayout(LayoutKind.Auto)] public readonly partial struct MemoryValueEnumerable : IValueReadOnlyList.DisposableEnumerator> @@ -27,19 +26,18 @@ public static MemoryValueEnumerable AsValueEnumerable(this Rea internal MemoryValueEnumerable(ReadOnlyMemory source) => this.source = source; - public readonly int Count + public int Count { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => source.Length; } - public readonly TSource this[int index] + public TSource this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => source.Span[index]; } - TSource IReadOnlyList.this[int index] - => source.Span[index]; + TSource IList.this[int index] { get => source.Span[index]; @@ -50,14 +48,17 @@ internal MemoryValueEnumerable(ReadOnlyMemory source) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SpanEnumerator GetEnumerator() + public SpanEnumerator GetEnumerator() => new(source.Span); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() + + DisposableEnumerator IValueEnumerable.GetEnumerator() => new(source); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(source); @@ -65,13 +66,9 @@ internal MemoryValueEnumerable(ReadOnlyMemory source) bool ICollection.IsReadOnly => true; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(Span span) - => source.Span.CopyTo(span); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyTo(TSource[] array, int arrayIndex) - => CopyTo(array.AsSpan(arrayIndex)); + => source.Span.CopyTo(array.AsSpan(arrayIndex)); [MethodImpl(MethodImplOptions.AggressiveInlining)] bool ICollection.Contains(TSource item) @@ -147,54 +144,10 @@ public MemoryValueEnumerable AsEnumerable() public MemoryValueEnumerable AsValueEnumerable() => this; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory ToArray() - => source.Span.ToArray(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.Span.ToArray(memoryPool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.Span.ToList(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.Span.ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => source.Span.ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.Span.ToDictionary(keySelector, elementSelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => source.Span.ToDictionary(keySelector, elementSelector, comparer); - #endregion #region Element - public Option ElementAt(int index) - => source.Span.ElementAt(index); - - public Option First() - => source.Span.First(); - - public Option Single() - => source.Span.Single(); - #endregion #region Filtering @@ -223,11 +176,14 @@ public Option Single() [MethodImpl(MethodImplOptions.AggressiveInlining)] public MemoryValueEnumerable Skip(int count) - => new(source.Skip(count)); + { + var (newOffset, newCount) = Utils.Skip(source.Length, count); + return new MemoryValueEnumerable(source.Slice(newOffset, newCount)); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public MemoryValueEnumerable Take(int count) - => new(source.Take(count)); + => new(source.Slice(0, Utils.Take(source.Length, count))); #endregion @@ -268,50 +224,6 @@ public MemoryValueEnumerable Take(int count) #region Quantifier - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate predicate) - where TPredicate : struct, IFunction - => source.Span.All(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => source.Span.All(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate predicate) - where TPredicate : struct, IFunction - => source.Span.AllAt(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Span.Any(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => source.Span.Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate predicate) - where TPredicate : struct, IFunction - => source.Span.Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => source.Span.Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate predicate) - where TPredicate : struct, IFunction - => source.Span.AnyAt(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource value, IEqualityComparer? comparer = null) - => source.Span.Contains(value, comparer); - #endregion #region Set @@ -325,43 +237,59 @@ public MemoryDistinctEnumerable Distinct(IEqualityComparer? co [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.SumVector(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemoryValueEnumerable source) + => source.source.Span.SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemoryValueEnumerable source) + => source.source.Span.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemoryValueEnumerable source) + => source.source.Span.SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemoryValueEnumerable source) + => source.source.Span.Sum(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.SumVector(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.Sum(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.SumVector(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.Sum(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.SumVector(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.Sum(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.Sum(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this MemoryValueEnumerable source) - => source.source.Span.Sum(); + => source.source.Span.Sum(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool ContainsVector(this MemoryValueEnumerable source, TSource value) @@ -369,17 +297,17 @@ public static bool ContainsVector(this MemoryValueEnumerable s => source.source.Span.ContainsVector(value); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static MemorySelectVectorContext, Vector>, FunctionWrapper> SelectVector(this MemoryValueEnumerable source, Func, Vector> vectorSelector, Func selector) + public static SpanSelectVectorContext, Vector>, FunctionWrapper> SelectVector(this MemoryValueEnumerable source, Func, Vector> vectorSelector, Func selector) where TSource : struct where TResult : struct - => source.source.SelectVector(vectorSelector, selector); + => source.source.Span.SelectVector(vectorSelector, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static MemorySelectVectorContext SelectVector(this MemoryValueEnumerable source, TVectorSelector vectorSelector = default, TSelector selector = default) + public static SpanSelectVectorContext SelectVector(this MemoryValueEnumerable source, TVectorSelector vectorSelector = default, TSelector selector = default) where TVectorSelector : struct, IFunction, Vector> where TSelector : struct, IFunction where TSource : struct where TResult : struct - => source.source.SelectVector(vectorSelector, selector); + => source.source.Span.SelectVector(vectorSelector, selector); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs new file mode 100644 index 000000000..ac5a927cf --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs @@ -0,0 +1,160 @@ +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SpanValueEnumerable AsValueEnumerable(this ReadOnlySpan source) + => new(source); + + [StructLayout(LayoutKind.Auto)] + public readonly ref partial struct SpanValueEnumerable + { + internal readonly ReadOnlySpan source; + + internal SpanValueEnumerable(ReadOnlySpan source) + => this.source = source; + + public ReadOnlySpan Span + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source; + } + + public int Count + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source.Length; + } + + public TSource this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SpanEnumerator GetEnumerator() + => new(source); + + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SpanValueEnumerable Skip(int count) + { + var (newOffset, newCount) = Utils.Skip(source.Length, count); + return new SpanValueEnumerable(source.Slice(newOffset, newCount)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SpanValueEnumerable Take(int count) + => new(source.Slice(0, Utils.Take(source.Length, count))); + + #endregion + + public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) + { + comparer ??= EqualityComparer.Default; + + var enumerator = GetEnumerator(); + using var otherEnumerator = other.GetEnumerator(); + while (true) + { + var thisEnded = !enumerator.MoveNext(); + var otherEnded = !otherEnumerator.MoveNext(); + + if (thisEnded != otherEnded) + return false; + + if (thisEnded) + return true; + + if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) + return false; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SpanValueEnumerable source) + => source.source.SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SpanValueEnumerable source) + => source.source.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanValueEnumerable source) + => source.source.SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanValueEnumerable source) + => source.source.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanValueEnumerable source) + => source.source.SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanValueEnumerable source) + => source.source.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SpanValueEnumerable source) + => source.source.SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SpanValueEnumerable source) + => source.source.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SpanValueEnumerable source) + => source.source.SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SpanValueEnumerable source) + => source.source.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SpanValueEnumerable source) + => source.source.SumVector(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SpanValueEnumerable source) + => source.source.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SpanValueEnumerable source) + => source.source.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SpanValueEnumerable source) + => source.source.Sum(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsVector(this SpanValueEnumerable source, TSource value) + where TSource : struct + => source.source.ContainsVector(value); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SpanSelectVectorContext, Vector>, FunctionWrapper> SelectVector(this SpanValueEnumerable source, Func, Vector> vectorSelector, Func selector) + where TSource : struct + where TResult : struct + => source.source.SelectVector(vectorSelector, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SpanSelectVectorContext SelectVector(this SpanValueEnumerable source, TVectorSelector vectorSelector = default, TSelector selector = default) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + where TSource : struct + where TResult : struct + => source.source.SelectVector(vectorSelector, selector); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Partitioning/Take/Take.Span.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.Span.cs similarity index 55% rename from NetFabric.Hyperlinq/Partitioning/Take/Take.Span.cs rename to NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.Span.cs index 205ff8ba3..3384b4eac 100644 --- a/NetFabric.Hyperlinq/Partitioning/Take/Take.Span.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/AsValueEnumerable.Span.cs @@ -5,9 +5,10 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span Take(this Span source, int count) - => source.Slice(0, Utils.Take(source.Length, count)); + public static SpanValueEnumerable AsValueEnumerable(this Span source) + => source.AsReadOnlySpan().AsValueEnumerable(); } -} +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/SpanEnumerator.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/SpanEnumerator.cs similarity index 100% rename from NetFabric.Hyperlinq/Conversion/AsValueEnumerable/SpanEnumerator.cs rename to NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/SpanEnumerator.cs diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/ValueEnumerator.cs b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/ValueEnumerator.cs similarity index 93% rename from NetFabric.Hyperlinq/Conversion/AsValueEnumerable/ValueEnumerator.cs rename to NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/ValueEnumerator.cs index 4b2f8d605..4a63dbf91 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/ValueEnumerator.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/AsValueEnumerable/ValueEnumerator.cs @@ -20,8 +20,6 @@ public TSource Current [MethodImpl(MethodImplOptions.AggressiveInlining)] get => enumerator.Current; } - TSource IEnumerator.Current - => enumerator.Current; object? IEnumerator.Current // ReSharper disable once HeapView.PossibleBoxingAllocation => enumerator.Current; diff --git a/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ReadOnlySpan.cs new file mode 100644 index 000000000..844bf3341 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ReadOnlySpan.cs @@ -0,0 +1,172 @@ +using System; +using System.Buffers; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + static partial class ArrayExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static TSource[] ToArray(this ReadOnlySpan source) + => source.ToArray(); + + public static Lease ToArray(this ReadOnlySpan source, ArrayPool pool, bool clearOnDispose = default) + { + if (source.Length is 0) + return Lease.Empty(); + + var result = pool.Lease(source.Length, clearOnDispose); + Copy(source, result.Memory.Span); + return result; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + static TSource[] ToArray(this ReadOnlySpan source, TPredicate predicate) + where TPredicate : struct, IFunction + { + if (source.Length is 0) + return Array.Empty(); + + using var arrayBuilder = ToArrayBuilder(source, ArrayPool.Shared, clearOnDispose: false, predicate); + return arrayBuilder.ToArray(); + } + + static Lease ToArray(this ReadOnlySpan source, ArrayPool pool, bool clearOnDispose, TPredicate predicate) + where TPredicate : struct, IFunction + { + if (source.Length is 0) + return Lease.Empty(); + + using var arrayBuilder = ToArrayBuilder(source, pool, clearOnDispose, predicate); + return arrayBuilder.ToArray(pool, clearOnDispose); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + + static TSource[] ToArrayAt(this ReadOnlySpan source, TPredicate predicate) + where TPredicate : struct, IFunction + { + if (source.Length is 0) + return Array.Empty(); + + using var arrayBuilder = ToArrayBuilderAt(source, ArrayPool.Shared, clearOnDispose: false, predicate); + return arrayBuilder.ToArray(); + } + + static Lease ToArrayAt(this ReadOnlySpan source, ArrayPool pool, bool clearOnDispose, TPredicate predicate) + where TPredicate : struct, IFunction + { + if (source.Length is 0) + return Lease.Empty(); + + using var arrayBuilder = ToArrayBuilderAt(source, pool, clearOnDispose, predicate); + return arrayBuilder.ToArray(pool, clearOnDispose); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + + static TResult[] ToArray(this ReadOnlySpan source, TSelector selector) + where TSelector : struct, IFunction + { + if (source.Length is 0) + return Array.Empty(); + + var result = Utils.AllocateUninitializedArray(source.Length); + Copy(source, result.AsSpan(), selector); + return result; + } + + static TResult[] ToArrayVector(this ReadOnlySpan source, TVectorSelector vectorSelector, TSelector selector) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + where TSource : struct + where TResult : struct + { + if (source.Length is 0) + return Array.Empty(); + + var result = Utils.AllocateUninitializedArray(source.Length); + CopyVector(source, result.AsSpan(), vectorSelector, selector); + return result; + } + + static Lease ToArrayVector(this ReadOnlySpan source, ArrayPool pool, bool clearOnDispose, TVectorSelector vectorSelector, TSelector selector) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + where TSource : struct + where TResult : struct + { + if (source.Length is 0) + return Lease.Empty(); + + var result = pool.Lease(source.Length, clearOnDispose); + CopyVector(source, result.Memory.Span, vectorSelector, selector); + return result; + } + + static Lease ToArray(this ReadOnlySpan source, ArrayPool pool, bool clearOnDispose, TSelector selector) + where TSelector : struct, IFunction + { + if (source.Length is 0) + return Lease.Empty(); + + var result = pool.Lease(source.Length, clearOnDispose); + Copy(source, result.Memory.Span, selector); + return result; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + static TResult[] ToArrayAt(this ReadOnlySpan source, TSelector selector) + where TSelector : struct, IFunction + { + if (source.Length is 0) + return Array.Empty(); + + var result = Utils.AllocateUninitializedArray(source.Length); + CopyAt(source, result.AsSpan(), selector); + return result; + } + + static Lease ToArrayAt(this ReadOnlySpan source, ArrayPool pool, bool clearOnDispose, TSelector selector) + where TSelector : struct, IFunction + { + if (source.Length is 0) + return Lease.Empty(); + + var result = pool.Lease(source.Length, clearOnDispose); + CopyAt(source, result.Memory.Span, selector); + return result; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + + static TResult[] ToArray(this ReadOnlySpan source, TPredicate predicate, TSelector selector) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + { + if (source.Length is 0) + return Array.Empty(); + + using var arrayBuilder = ToArrayBuilder(source, ArrayPool.Shared, false, predicate, selector); + return arrayBuilder.ToArray(); + } + + static Lease ToArray(this ReadOnlySpan source, ArrayPool pool, bool clearOnDispose, TPredicate predicate, TSelector selector) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + { + if (source.Length is 0) + return Lease.Empty(); + + using var arrayBuilder = ToArrayBuilder(source, pool, clearOnDispose, predicate, selector); + return arrayBuilder.ToArray(pool, clearOnDispose); + } + } +} + diff --git a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ValueEnumerable.cs similarity index 61% rename from NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ValueEnumerable.cs index 921c895cf..33ce977bc 100644 --- a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ValueEnumerable.cs @@ -1,8 +1,6 @@ using System; using System.Buffers; using System.Collections.Generic; -using System.Diagnostics; -using System.Numerics; using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq @@ -14,149 +12,143 @@ public static partial class ValueEnumerableExtensions where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator { - return source switch - { - ICollection collection => BuildArrayFromCollection(collection), - _ => BuildArray(source) - }; - - static TSource[] BuildArrayFromCollection(ICollection collection) + // ReSharper disable once HeapView.PossibleBoxingAllocation + if (source is ICollection collection) { + if (collection.Count is 0) + return Array.Empty(); + var result = Utils.AllocateUninitializedArray(collection.Count); collection.CopyTo(result, 0); - return result; - } - - static TSource[] BuildArray(TEnumerable source) - { - using var arrayBuilder = ToArrayBuilder(source, ArrayPool.Shared); - return arrayBuilder.ToArray(); + return result; } + + using var arrayBuilder = ToArrayBuilder(source, ArrayPool.Shared, false); + return arrayBuilder.ToArray(); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IMemoryOwner ToArray(this TEnumerable source, MemoryPool pool) + public static Lease ToArray(this TEnumerable source, ArrayPool pool, bool clearOnDispose = default) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator { - using var arrayBuilder = ToArrayBuilder(source, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); + // ReSharper disable once HeapView.PossibleBoxingAllocation + if (source is ICollection collection) + { + if (collection.Count is 0) + return Lease.Empty(); + + var result = pool.Lease(collection.Count, clearOnDispose); + collection.CopyTo(result.Rented, 0); + return result; + } + + using var arrayBuilder = ToArrayBuilder(source, pool, clearOnDispose); + return arrayBuilder.ToArray(pool, clearOnDispose); } ////////////////////////////////////////////////////////////////////////////////////////////////// - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static TSource[] ToArray(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction { - using var arrayBuilder = ToArrayBuilder(source, predicate, ArrayPool.Shared); + using var arrayBuilder = ToArrayBuilder(source, ArrayPool.Shared, false, predicate); return arrayBuilder.ToArray(); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static IMemoryOwner ToArray(this TEnumerable source, TPredicate predicate, MemoryPool pool) + internal static Lease ToArray(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction { - using var arrayBuilder = ToArrayBuilder(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); + using var arrayBuilder = ToArrayBuilder(source, pool, clearOnDispose, predicate); + return arrayBuilder.ToArray(pool, clearOnDispose); } ////////////////////////////////////////////////////////////////////////////////////////////////// - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static TSource[] ToArrayAt(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction { - using var arrayBuilder = ToArrayBuilderAt(source, predicate, ArrayPool.Shared); + using var arrayBuilder = ToArrayBuilderAt(source, ArrayPool.Shared, false, predicate); return arrayBuilder.ToArray(); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static IMemoryOwner ToArrayAt(this TEnumerable source, TPredicate predicate, MemoryPool pool) + internal static Lease ToArrayAt(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction { - using var arrayBuilder = ToArrayBuilderAt(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); + using var arrayBuilder = ToArrayBuilderAt(source, pool, clearOnDispose, predicate); + return arrayBuilder.ToArray(pool, clearOnDispose); } ////////////////////////////////////////////////////////////////////////////////////////////////// - [MethodImpl(MethodImplOptions.AggressiveInlining)] static TResult[] ToArray(this TEnumerable source, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction { - using var arrayBuilder = ToArrayBuilder(source, selector, ArrayPool.Shared); + using var arrayBuilder = ToArrayBuilder(source, ArrayPool.Shared, false, selector); return arrayBuilder.ToArray(); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this TEnumerable source, TSelector selector, MemoryPool pool) + static Lease ToArray(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction { - using var arrayBuilder = ToArrayBuilder(source, selector, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); + using var arrayBuilder = ToArrayBuilder(source, pool, clearOnDispose, selector); + return arrayBuilder.ToArray(pool, clearOnDispose); } ////////////////////////////////////////////////////////////////////////////////////////////////// - [MethodImpl(MethodImplOptions.AggressiveInlining)] static TResult[] ToArrayAt(this TEnumerable source, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction { - using var arrayBuilder = ToArrayBuilderAt(source, selector, ArrayPool.Shared); + using var arrayBuilder = ToArrayBuilderAt(source, ArrayPool.Shared, false, selector); return arrayBuilder.ToArray(); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayAt(this TEnumerable source, TSelector selector, MemoryPool pool) + static Lease ToArrayAt(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction { - using var arrayBuilder = ToArrayBuilderAt(source, selector, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); + using var arrayBuilder = ToArrayBuilderAt(source, pool, clearOnDispose, selector); + return arrayBuilder.ToArray(pool, clearOnDispose); } ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static TResult[] ToArray(this TEnumerable source, TPredicate predicate, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction where TSelector : struct, IFunction { - using var arrayBuilder = ToArrayBuilder(source, predicate, selector, ArrayPool.Shared); + using var arrayBuilder = ToArrayBuilder(source, ArrayPool.Shared, false, predicate, selector); return arrayBuilder.ToArray(); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static IMemoryOwner ToArray(this TEnumerable source, TPredicate predicate, TSelector selector, MemoryPool pool) + internal static Lease ToArray(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TPredicate predicate, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction where TSelector : struct, IFunction { - using var arrayBuilder = ToArrayBuilder(source, predicate, selector, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); + using var arrayBuilder = ToArrayBuilder(source, pool, clearOnDispose, predicate, selector); + return arrayBuilder.ToArray(pool, clearOnDispose); } } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ValueReadOnlyCollection.cs new file mode 100644 index 000000000..e0d85d4d8 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ValueReadOnlyCollection.cs @@ -0,0 +1,159 @@ +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyCollectionExtensions + { + + public static TSource[] ToArray(this TEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + { + if (source.Count is 0) + return Array.Empty(); + + var result = Utils.AllocateUninitializedArray(source.Count); + // ReSharper disable once HeapView.PossibleBoxingAllocation + if (source is ICollection collection) + collection.CopyTo(result, 0); + else + Copy(source, result); + return result; + } + + public static Lease ToArray(this TEnumerable source, ArrayPool pool, bool clearOnDispose = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + { + if (source.Count is 0) + return Lease.Empty(); + + var result = pool.Lease(source.Count, clearOnDispose); + // ReSharper disable once HeapView.PossibleBoxingAllocation + if (source is ICollection collection) + collection.CopyTo(result.Rented, 0); + else + Copy(source, result.Rented); + return result; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + static TSource[] ToArray(this TEnumerable source, + TPredicate predicate) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.Count is 0 + ? Array.Empty() + : ValueEnumerableExtensions.ToArray(source, predicate); + + static Lease ToArray(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TPredicate predicate) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.Count is 0 + ? Lease.Empty() + : ValueEnumerableExtensions.ToArray(source, pool, clearOnDispose, predicate); + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + static TSource[] ToArrayAt(this TEnumerable source, TPredicate predicate) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.Count is 0 + ? Array.Empty() + : ValueEnumerableExtensions.ToArrayAt(source, predicate); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static Lease ToArrayAt(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TPredicate predicate) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.Count is 0 + ? Lease.Empty() + : ValueEnumerableExtensions.ToArrayAt(source, pool, clearOnDispose, predicate); + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + internal static TResult[] ToArray(this TEnumerable source, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + if (source.Count is 0) + return Array.Empty(); + + var result = Utils.AllocateUninitializedArray(source.Count); + Copy(source, result, selector); + return result; + } + + internal static Lease ToArray(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + if (source.Count is 0) + return Lease.Empty(); + + var result = pool.Lease(source.Count, clearOnDispose); + Copy(source, result.Rented, selector); + return result; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + + internal static TResult[] ToArrayAt(this TEnumerable source, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + if (source.Count is 0) + return Array.Empty(); + + var result = Utils.AllocateUninitializedArray(source.Count); + CopyAt(source, result, selector); + return result; + } + + internal static Lease ToArrayAt(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + if (source.Count is 0) + return Lease.Empty(); + + var result = pool.Lease(source.Count, clearOnDispose); + CopyAt(source, result.Rented, selector); + return result; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + static TResult[] ToArray(this TEnumerable source, TPredicate predicate, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.Count is 0 + ? Array.Empty() + : ValueEnumerableExtensions.ToArray(source, predicate, selector); + + static Lease ToArray(this TEnumerable source, ArrayPool pool, bool clearOnDispose, TPredicate predicate, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.Count is 0 + ? Lease.Empty() + : ValueEnumerableExtensions.ToArray(source, pool, clearOnDispose, predicate, selector); + } +} diff --git a/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ValueReadOnlyList.cs new file mode 100644 index 000000000..1ea33e6da --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArray.ValueReadOnlyList.cs @@ -0,0 +1,24 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TSource[] ToArray(this TEnumerable source) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.ToArray(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Lease ToArray(this TEnumerable source, ArrayPool pool, bool clearOnDispose = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.ToArray(source, pool, clearOnDispose); + } +} diff --git a/NetFabric.Hyperlinq/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.cs similarity index 61% rename from NetFabric.Hyperlinq/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.cs index 4052f1c3c..58bfebf82 100644 --- a/NetFabric.Hyperlinq/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/ToArray/ToArrayAsync.AsyncValueEnumerable.cs @@ -1,5 +1,4 @@ -using System; -using System.Buffers; +using System.Buffers; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading; @@ -14,94 +13,104 @@ public static partial class AsyncValueEnumerableExtensions public static async ValueTask ToArrayAsync(this TEnumerable source, CancellationToken cancellationToken = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator - => (await source.ToArrayBuilderAsync(ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(); + => (await source.ToArrayBuilderAsync(ArrayPool.Shared, false, cancellationToken).ConfigureAwait(false)).ToArray(); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static async ValueTask> ToArrayAsync(this TEnumerable source, MemoryPool pool, CancellationToken cancellationToken = default) + public static async ValueTask> ToArrayAsync(this TEnumerable source, ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator - => (await source.ToArrayBuilderAsync(ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(pool); + => (await source.ToArrayBuilderAsync(pool, clearOnDispose, cancellationToken).ConfigureAwait(false)).ToArray(pool, clearOnDispose); ////////////////////////////////////////////////////////////////////////////////////////////////// + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask ToArrayAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + static async ValueTask ToArrayAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction - => (await source.ToArrayBuilderAsync(predicate, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(); + => (await source.ToArrayBuilderAsync(ArrayPool.Shared, false, cancellationToken, predicate).ConfigureAwait(false)).ToArray(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToArrayAsync(this TEnumerable source, TPredicate predicate, MemoryPool pool, CancellationToken cancellationToken) + static async ValueTask> ToArrayAsync(this TEnumerable source, ArrayPool pool, bool clearOnDispose, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction - => (await source.ToArrayBuilderAsync(predicate, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(pool); + => (await source.ToArrayBuilderAsync(pool, clearOnDispose, cancellationToken, predicate).ConfigureAwait(false)).ToArray(pool, clearOnDispose); ////////////////////////////////////////////////////////////////////////////////////////////////// + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask ToArrayAtAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + static async ValueTask ToArrayAtAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction - => (await source.ToArrayBuilderAtAsync(predicate, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(); + => (await source.ToArrayBuilderAtAsync(ArrayPool.Shared, false, cancellationToken, predicate).ConfigureAwait(false)).ToArray(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToArrayAtAsync(this TEnumerable source, TPredicate predicate, MemoryPool pool, CancellationToken cancellationToken) + static async ValueTask> ToArrayAtAsync(this TEnumerable source, ArrayPool pool, bool clearOnDispose, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction - => (await source.ToArrayBuilderAtAsync(predicate, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(pool); + => (await source.ToArrayBuilderAtAsync(pool, clearOnDispose, cancellationToken, predicate).ConfigureAwait(false)).ToArray(pool, clearOnDispose); ////////////////////////////////////////////////////////////////////////////////////////////////// + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask ToArrayAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken) + static async ValueTask ToArrayAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction - => (await source.ToArrayBuilderAsync(selector, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(); + => (await source.ToArrayBuilderAsync(ArrayPool.Shared, false, cancellationToken, selector).ConfigureAwait(false)).ToArray(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToArrayAsync(this TEnumerable source, TSelector selector, MemoryPool pool, CancellationToken cancellationToken) + static async ValueTask> ToArrayAsync(this TEnumerable source, ArrayPool pool, CancellationToken cancellationToken, bool clearOnDispose, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction - => (await source.ToArrayBuilderAsync(selector, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(pool); + => (await source.ToArrayBuilderAsync(pool, clearOnDispose, cancellationToken, selector).ConfigureAwait(false)).ToArray(pool, clearOnDispose); ////////////////////////////////////////////////////////////////////////////////////////////////// + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask ToArrayAtAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken) + static async ValueTask ToArrayAtAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction - => (await source.ToArrayBuilderAtAsync(selector, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(); + => (await source.ToArrayBuilderAtAsync(ArrayPool.Shared, false, cancellationToken, selector).ConfigureAwait(false)).ToArray(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToArrayAtAsync(this TEnumerable source, TSelector selector, MemoryPool pool, CancellationToken cancellationToken) + static async ValueTask> ToArrayAtAsync(this TEnumerable source, ArrayPool pool, CancellationToken cancellationToken, bool clearOnDispose, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction - => (await source.ToArrayBuilderAtAsync(selector, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(pool); + => (await source.ToArrayBuilderAtAsync(pool, clearOnDispose, cancellationToken, selector).ConfigureAwait(false)).ToArray(pool, clearOnDispose); ////////////////////////////////////////////////////////////////////////////////////////////////// + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask ToArrayAsync(this TEnumerable source, TPredicate predicate, TSelector selector, CancellationToken cancellationToken) + static async ValueTask ToArrayAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction where TSelector : struct, IAsyncFunction - => (await source.ToArrayBuilderAsync(predicate, selector, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(); + => (await source.ToArrayBuilderAsync(ArrayPool.Shared, false, cancellationToken, predicate, selector).ConfigureAwait(false)).ToArray(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToArrayAsync(this TEnumerable source, TPredicate predicate, TSelector selector, MemoryPool pool, CancellationToken cancellationToken) + static async ValueTask> ToArrayAsync(this TEnumerable source, ArrayPool pool, bool clearOnDispose, CancellationToken cancellationToken, TPredicate predicate, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction where TSelector : struct, IAsyncFunction - => (await source.ToArrayBuilderAsync(predicate, selector, ArrayPool.Shared, cancellationToken).ConfigureAwait(false)).ToArray(pool); + => (await source.ToArrayBuilderAsync(pool, clearOnDispose, cancellationToken, predicate, selector).ConfigureAwait(false)).ToArray(pool, clearOnDispose); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ReadOnlySpan.cs new file mode 100644 index 000000000..a01acfc42 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ReadOnlySpan.cs @@ -0,0 +1,166 @@ + using System; +using System.Collections.Generic; + using System.Runtime.CompilerServices; + + namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static Dictionary ToDictionary(this ReadOnlySpan source, Func keySelector, IEqualityComparer? comparer = default) + where TKey : notnull + => source.ToDictionary(new FunctionWrapper(keySelector), comparer); + + + static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + var dictionary = new Dictionary(source.Length, comparer); + foreach (var item in source) + dictionary.Add(keySelector.Invoke(item), item); + return dictionary; + } + + + static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) + where TKey : notnull + where TKeySelector : struct, IFunction + where TPredicate : struct, IFunction + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + var dictionary = new Dictionary(source.Length, comparer); + foreach (var item in source) + { + if (predicate.Invoke(item)) + dictionary.Add(keySelector.Invoke(item), item); + } + return dictionary; + } + + + static Dictionary ToDictionaryAt(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) + where TKey : notnull + where TKeySelector : struct, IFunction + where TPredicate : struct, IFunction + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + var dictionary = new Dictionary(source.Length, comparer); + for (var index = 0; index < source.Length; index++) + { + var item = source[index]; + if (predicate.Invoke(item, index)) + dictionary.Add(keySelector.Invoke(item), item); + } + return dictionary; + } + + + static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) + where TKey : notnull + where TKeySelector : struct, IFunction + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + var dictionary = new Dictionary(source.Length, comparer); + foreach (var item in source) + { + if (predicate.Invoke(item)) + { + var result = selector.Invoke(item); + dictionary.Add(keySelector.Invoke(result), result); + } + } + return dictionary; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static Dictionary ToDictionary(this ReadOnlySpan source, Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) + where TKey : notnull + => source.ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); + + + static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + where TElementSelector : struct, IFunction + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + var dictionary = new Dictionary(source.Length, comparer); + foreach (var item in source) + dictionary.Add(keySelector.Invoke(item), elementSelector.Invoke(item)); + return dictionary; + } + + + static Dictionary + ToDictionary( + this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, + IEqualityComparer? comparer, TPredicate predicate) + where TKey : notnull + where TKeySelector : struct, IFunction + where TElementSelector : struct, IFunction + where TPredicate : struct, IFunction + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + var dictionary = new Dictionary(source.Length, comparer); + foreach (var item in source) + { + if (predicate.Invoke(item)) + dictionary.Add(keySelector.Invoke(item), elementSelector.Invoke(item)); + } + return dictionary; + } + + + static Dictionary + ToDictionaryAt( + this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, + IEqualityComparer? comparer, TPredicate predicate) + where TKey : notnull + where TKeySelector : struct, IFunction + where TElementSelector : struct, IFunction + where TPredicate : struct, IFunction + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + var dictionary = new Dictionary(source.Length, comparer); + for (var index = 0; index < source.Length; index++) + { + var item = source[index]; + if (predicate.Invoke(item, index)) + dictionary.Add(keySelector.Invoke(item), elementSelector.Invoke(item)); + } + + return dictionary; + } + + + static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) + where TKey : notnull + where TKeySelector : struct, IFunction + where TElementSelector : struct, IFunction + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + var dictionary = new Dictionary(source.Length, comparer); + foreach (var item in source) + { + if (predicate.Invoke(item)) + { + var result = selector.Invoke(item); + dictionary.Add(keySelector.Invoke(result), elementSelector.Invoke(result)); + } + } + + return dictionary; + } + } +} + diff --git a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ValueEnumerable.cs similarity index 86% rename from NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ValueEnumerable.cs index c2415a224..72e8f2c28 100644 --- a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ValueEnumerable.cs @@ -8,13 +8,6 @@ namespace NetFabric.Hyperlinq public static partial class ValueEnumerableExtensions { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this TEnumerable source, Func keySelector, IEqualityComparer? comparer = default) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TKey : notnull - => source.ToDictionary>(new FunctionWrapper(keySelector), comparer); - public static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer = default) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -31,6 +24,7 @@ public static partial class ValueEnumerableExtensions return dictionary; } + internal static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -50,6 +44,7 @@ public static partial class ValueEnumerableExtensions } + internal static Dictionary ToDictionaryAt(this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -71,6 +66,7 @@ public static partial class ValueEnumerableExtensions } } + internal static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -95,13 +91,6 @@ public static partial class ValueEnumerableExtensions ////////////////////////////////////////////////////////////////////////////////////////////////// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this TEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TKey : notnull - => source.ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - public static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -121,6 +110,7 @@ public static partial class ValueEnumerableExtensions return dictionary; } + internal static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -140,6 +130,7 @@ public static partial class ValueEnumerableExtensions return dictionary; } + internal static Dictionary ToDictionaryAt(this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -162,6 +153,7 @@ public static partial class ValueEnumerableExtensions } } + internal static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator diff --git a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ValueReadOnlyCollection.cs similarity index 85% rename from NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ValueReadOnlyCollection.cs index ed7c55c97..da53b8cae 100644 --- a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ValueReadOnlyCollection.cs @@ -6,13 +6,6 @@ namespace NetFabric.Hyperlinq { public static partial class ValueReadOnlyCollectionExtensions { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this TEnumerable source, Func keySelector, IEqualityComparer? comparer = default) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TKey : notnull - => ToDictionary>(source, new FunctionWrapper(keySelector), comparer); public static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer = default) where TEnumerable : IValueReadOnlyCollection @@ -24,6 +17,7 @@ public static partial class ValueReadOnlyCollectionExtensions ? new Dictionary() : ValueEnumerableExtensions.ToDictionary(source, keySelector, comparer); + static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator @@ -36,6 +30,7 @@ public static partial class ValueReadOnlyCollectionExtensions : ValueEnumerableExtensions.ToDictionary(source, keySelector, comparer, predicate); + static Dictionary ToDictionaryAt(this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator @@ -47,6 +42,7 @@ public static partial class ValueReadOnlyCollectionExtensions ? new Dictionary() : ValueEnumerableExtensions.ToDictionaryAt(source, keySelector, comparer, predicate); + static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator @@ -61,13 +57,6 @@ public static partial class ValueReadOnlyCollectionExtensions ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this TEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TKey : notnull - => ToDictionary, FunctionWrapper>(source, new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); public static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) where TEnumerable : IValueReadOnlyCollection @@ -81,6 +70,7 @@ public static partial class ValueReadOnlyCollectionExtensions : ValueEnumerableExtensions.ToDictionary(source, keySelector, elementSelector, comparer); + static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator @@ -94,6 +84,7 @@ public static partial class ValueReadOnlyCollectionExtensions : ValueEnumerableExtensions.ToDictionary(source, keySelector, elementSelector, comparer, predicate); + static Dictionary ToDictionaryAt(this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator @@ -106,6 +97,7 @@ public static partial class ValueReadOnlyCollectionExtensions ? new Dictionary() : ValueEnumerableExtensions.ToDictionaryAt(source, keySelector, elementSelector, comparer, predicate); + static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator diff --git a/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ValueReadOnlyList.cs new file mode 100644 index 000000000..edac0afbb --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionary.ValueReadOnlyList.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TKey : notnull + where TKeySelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.ToDictionary(source, keySelector, comparer); + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Dictionary ToDictionary(this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TKey : notnull + where TKeySelector : struct, IFunction + where TElementSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.ToDictionary(source, keySelector, elementSelector, comparer); + } +} + diff --git a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionaryAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionaryAsync.AsyncValueEnumerable.cs similarity index 86% rename from NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionaryAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionaryAsync.AsyncValueEnumerable.cs index 8bd23b0a6..e098c5d12 100644 --- a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionaryAsync.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/ToDictionary/ToDictionaryAsync.AsyncValueEnumerable.cs @@ -9,21 +9,11 @@ namespace NetFabric.Hyperlinq { public static partial class AsyncValueEnumerableExtensions { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueTask> ToDictionaryAsync( - this TEnumerable source, - Func> keySelector, - IEqualityComparer? comparer = null, - CancellationToken cancellationToken = default) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TKey : notnull - => source.ToDictionaryAsync>(new AsyncFunctionWrapper(keySelector), comparer, cancellationToken); public static ValueTask> ToDictionaryAsync( this TEnumerable source, TKeySelector keySelector, - IEqualityComparer? comparer = null, + IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator @@ -58,12 +48,13 @@ public static partial class AsyncValueEnumerableExtensions } + static async ValueTask> ToDictionaryAsync( this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer, - TPredicate predicate, - CancellationToken cancellationToken) + CancellationToken cancellationToken, + TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TKey : notnull @@ -92,12 +83,13 @@ public static partial class AsyncValueEnumerableExtensions } + static async ValueTask> ToDictionaryAtAsync( this TEnumerable source, TKeySelector keySelector, IEqualityComparer? comparer, - TPredicate predicate, - CancellationToken cancellationToken) + CancellationToken cancellationToken, + TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TKey : notnull @@ -129,6 +121,7 @@ public static partial class AsyncValueEnumerableExtensions } } + static async ValueTask> ToDictionaryAsync( this TEnumerable source, TKeySelector keySelector, @@ -169,23 +162,11 @@ public static partial class AsyncValueEnumerableExtensions ////////////////////////////////////////////////////////////////////////////////////////////////// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueTask> ToDictionaryAsync( - this TEnumerable source, - Func> keySelector, - Func> elementSelector, - IEqualityComparer? comparer = null, - CancellationToken cancellationToken = default) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TKey : notnull - => source.ToDictionaryAsync, AsyncFunctionWrapper>(new AsyncFunctionWrapper(keySelector), new AsyncFunctionWrapper(elementSelector), comparer, cancellationToken); - public static ValueTask> ToDictionaryAsync( this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, - IEqualityComparer? comparer = null, + IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator @@ -220,13 +201,14 @@ public static partial class AsyncValueEnumerableExtensions } + static async ValueTask> ToDictionaryAsync( this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, - TPredicate predicate, - CancellationToken cancellationToken) + CancellationToken cancellationToken, + TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TKey : notnull @@ -256,13 +238,14 @@ public static partial class AsyncValueEnumerableExtensions } + static async ValueTask> ToDictionaryAtAsync( this TEnumerable source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, - TPredicate predicate, - CancellationToken cancellationToken) + CancellationToken cancellationToken, + TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TKey : notnull @@ -295,6 +278,7 @@ public static partial class AsyncValueEnumerableExtensions } + static async ValueTask> ToDictionaryAsync( this TEnumerable source, TKeySelector keySelector, diff --git a/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ReadOnlySpan.cs new file mode 100644 index 000000000..bb4f7dfb4 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ReadOnlySpan.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Runtime.CompilerServices; +// ReSharper disable HeapView.ObjectAllocation.Evident + +namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static List ToList(this ReadOnlySpan source) + => source.ToArray().AsList(); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static List ToList(this ReadOnlySpan source, TPredicate predicate) + where TPredicate : struct, IFunction + => source.ToArray(predicate).AsList(); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static List ToListAt(this ReadOnlySpan source, TPredicate predicate) + where TPredicate : struct, IFunction + => source.ToArrayAt(predicate).AsList(); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static List ToList(this ReadOnlySpan source, TSelector selector) + where TSelector : struct, IFunction + => source.ToArray(selector).AsList(); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static List ToListVector(this ReadOnlySpan source, TVectorSelector vectorSelector, TSelector selector) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + where TSource : struct + where TResult : struct + => source.ToArrayVector(vectorSelector, selector).AsList(); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static List ToListAt(this ReadOnlySpan source, TSelector selector) + where TSelector : struct, IFunction + => source.ToArrayAt(selector).AsList(); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static List ToList(this ReadOnlySpan source, TPredicate predicate, TSelector selector) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.ToArray(predicate, selector).AsList(); + } +} diff --git a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ValueEnumerable.cs similarity index 97% rename from NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ValueEnumerable.cs index 07f51b1b4..2b03337c3 100644 --- a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ValueEnumerable.cs @@ -1,7 +1,4 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Numerics; +using System.Collections.Generic; using System.Runtime.CompilerServices; // ReSharper disable HeapView.ObjectAllocation.Evident @@ -17,6 +14,7 @@ public static partial class ValueEnumerableExtensions => source.ToArray().AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] static List ToList(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable @@ -25,6 +23,7 @@ public static partial class ValueEnumerableExtensions => source.ToArray(predicate).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] static List ToListAt(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable @@ -33,6 +32,7 @@ public static partial class ValueEnumerableExtensions => source.ToArrayAt(predicate).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] static List ToList(this TEnumerable source, TSelector selector) where TEnumerable : IValueEnumerable @@ -41,6 +41,7 @@ public static partial class ValueEnumerableExtensions => source.ToArray(selector).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] static List ToListAt(this TEnumerable source, TSelector selector) where TEnumerable : IValueEnumerable @@ -48,6 +49,7 @@ public static partial class ValueEnumerableExtensions where TSelector : struct, IFunction => source.ToArrayAt(selector).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] static List ToList(this TEnumerable source, TPredicate predicate, TSelector selector) where TEnumerable : IValueEnumerable diff --git a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ValueReadOnlyCollection.cs similarity index 57% rename from NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ValueReadOnlyCollection.cs index d8ef06390..ae60dc6d8 100644 --- a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ValueReadOnlyCollection.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices.ComTypes; + // ReSharper disable HeapView.ObjectAllocation.Evident namespace NetFabric.Hyperlinq @@ -14,59 +14,41 @@ public static partial class ValueReadOnlyCollectionExtensions => source switch { { Count: 0 } => new List(), - _ => source switch - { - // ReSharper disable once HeapView.PossibleBoxingAllocation - ICollection collection => new List(collection), - - _ => ToArray(source).AsList(), - } + _ => ToArray(source).AsList(), }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] static List ToList(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction - => source switch - { - {Count: 0} => new List(), - _ => ToArray(source, predicate).AsList() - }; + => ToArray(source, predicate).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] static List ToListAt(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction - => source switch - { - {Count: 0} => new List(), - _ => ToArrayAt(source, predicate).AsList() - }; + => ToArrayAt(source, predicate).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToList(this TEnumerable source, - TSelector selector) + internal static List ToList(this TEnumerable source, TSelector selector) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction - => source switch - { - {Count: 0} => new List(), - _ => ToArray(source, selector).AsList() - }; + => ToArray(source, selector).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListAt(this TEnumerable source, TSelector selector) + internal static List ToListAt(this TEnumerable source, TSelector selector) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction - => source switch - { - {Count: 0} => new List(), - _ => ToArrayAt(source, selector).AsList() - }; + => ToArrayAt(source, selector).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] static List ToList(this TEnumerable source, TPredicate predicate, TSelector selector) @@ -74,10 +56,6 @@ public static partial class ValueReadOnlyCollectionExtensions where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction where TSelector : struct, IFunction - => source switch - { - {Count: 0} => new List(), - _ => ToArray(source, predicate, selector).AsList() - }; + => ToArray(source, predicate, selector).AsList(); } } diff --git a/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ValueReadOnlyList.cs new file mode 100644 index 000000000..e69e0402f --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToList.ValueReadOnlyList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static List ToList(this TEnumerable source) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.ToList(source); + } +} diff --git a/NetFabric.Hyperlinq/Conversion/ToList/ToListAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToListAsync.AsyncValueEnumerable.cs similarity index 80% rename from NetFabric.Hyperlinq/Conversion/ToList/ToListAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Conversion/ToList/ToListAsync.AsyncValueEnumerable.cs index 1f6d9b73e..3d4a0f681 100644 --- a/NetFabric.Hyperlinq/Conversion/ToList/ToListAsync.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Conversion/ToList/ToListAsync.AsyncValueEnumerable.cs @@ -1,5 +1,4 @@ -using System.Buffers; -using System.Collections.Generic; +using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -17,44 +16,49 @@ public static partial class AsyncValueEnumerableExtensions => (await source.ToArrayAsync(cancellationToken).ConfigureAwait(false)).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToListAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + static async ValueTask> ToListAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction - => (await source.ToArrayAsync(predicate, cancellationToken).ConfigureAwait(false)).AsList(); + => (await source.ToArrayAsync(cancellationToken, predicate).ConfigureAwait(false)).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToListAtAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + static async ValueTask> ToListAtAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction - => (await source.ToArrayAtAsync(predicate, cancellationToken).ConfigureAwait(false)).AsList(); + => (await source.ToArrayAtAsync(cancellationToken, predicate).ConfigureAwait(false)).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToListAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken) + static async ValueTask> ToListAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction - => (await source.ToArrayAsync(selector, cancellationToken).ConfigureAwait(false)).AsList(); + => (await source.ToArrayAsync(cancellationToken, selector).ConfigureAwait(false)).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToListAtAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken) + static async ValueTask> ToListAtAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction - => (await source.ToArrayAtAsync(selector, cancellationToken).ConfigureAwait(false)).AsList(); + => (await source.ToArrayAtAsync(cancellationToken, selector).ConfigureAwait(false)).AsList(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> ToListAsync(this TEnumerable source, TPredicate predicate, TSelector selector, CancellationToken cancellationToken) + static async ValueTask> ToListAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction where TSelector : struct, IAsyncFunction - => (await source.ToArrayAsync(predicate, selector, cancellationToken).ConfigureAwait(false)).AsList(); + => (await source.ToArrayAsync(cancellationToken, predicate, selector).ConfigureAwait(false)).AsList(); } } diff --git a/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ReadOnlyList.cs new file mode 100644 index 000000000..371ffb7d7 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ReadOnlyList.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ReadOnlyListExtensions + { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static Option ElementAt(this TList source, int index) + where TList : struct, IReadOnlyList + => index < 0 || index >= source.Count + ? Option.None + : Option.Some(source[index]); + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Option ElementAt(this TList source, int index, TSelector selector) + where TList : struct, IReadOnlyList + where TSelector : struct, IFunction + => index < 0 || index >= source.Count + ? Option.None + : Option.Some(selector.Invoke(source[index])); + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Option ElementAtAt(this TList source, int index, TSelector selector) + where TList : struct, IReadOnlyList + where TSelector : struct, IFunction + => index < 0 || index >= source.Count + ? Option.None + : Option.Some(selector.Invoke(source[index], index)); + } +} diff --git a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ReadOnlySpan.cs similarity index 94% rename from NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ReadOnlySpan.cs index d72d8e6a7..a452d86e8 100644 --- a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ReadOnlySpan.cs @@ -1,19 +1,19 @@ using System; -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Option ElementAt(this ReadOnlySpan source, int index) + static Option ElementAt(this ReadOnlySpan source, int index) => index < 0 || index >= source.Length ? Option.None : Option.Some(source[index]); + static Option ElementAt(this ReadOnlySpan source, int index, TPredicate predicate) where TPredicate : struct, IFunction { @@ -29,6 +29,7 @@ public static Option ElementAt(this ReadOnlySpan sour } + static Option ElementAtAt(this ReadOnlySpan source, int index, TPredicate predicate) where TPredicate : struct, IFunction { @@ -45,6 +46,7 @@ public static Option ElementAt(this ReadOnlySpan sour } + static Option ElementAt(this ReadOnlySpan source, int index, TSelector selector) where TSelector : struct, IFunction => index < 0 || index >= source.Length @@ -52,6 +54,7 @@ public static Option ElementAt(this ReadOnlySpan sour : Option.Some(selector.Invoke(source[index])); + static Option ElementAtAt(this ReadOnlySpan source, int index, TSelector selector) where TSelector : struct, IFunction => index < 0 || index >= source.Length @@ -59,6 +62,7 @@ public static Option ElementAt(this ReadOnlySpan sour : Option.Some(selector.Invoke(source[index], index)); + static Option ElementAt(this ReadOnlySpan source, int index, TPredicate predicate, TSelector selector) where TPredicate : struct, IFunction where TSelector : struct, IFunction diff --git a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ValueEnumerable.cs similarity index 99% rename from NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ValueEnumerable.cs index 16ad1c4a3..c79dfe2c5 100644 --- a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ValueEnumerable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace NetFabric.Hyperlinq @@ -24,6 +23,7 @@ public static partial class ValueEnumerableExtensions } + internal static Option ElementAt(this TEnumerable source, int index, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -42,6 +42,7 @@ public static partial class ValueEnumerableExtensions } + internal static Option ElementAtAt(this TEnumerable source, int index, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -63,6 +64,7 @@ public static partial class ValueEnumerableExtensions } + internal static Option ElementAt(this TEnumerable source, int index, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -82,6 +84,7 @@ public static partial class ValueEnumerableExtensions } + internal static Option ElementAtAt(this TEnumerable source, int index, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -103,6 +106,7 @@ public static partial class ValueEnumerableExtensions } + internal static Option ElementAt(this TEnumerable source, int index, TPredicate predicate, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator diff --git a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ValueReadOnlyCollection.cs similarity index 97% rename from NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ValueReadOnlyCollection.cs index 91f5cd2f4..80eb7020b 100644 --- a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ValueReadOnlyCollection.cs @@ -18,6 +18,7 @@ public static partial class ValueReadOnlyCollectionExtensions : Option.None }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option ElementAt(this TEnumerable source, int index, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection @@ -29,9 +30,9 @@ public static partial class ValueReadOnlyCollectionExtensions _ => ValueEnumerableExtensions.ElementAt(source, index, predicate) }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static Option ElementAtAt(this TEnumerable source, - int index, TPredicate predicate) + static Option ElementAtAt(this TEnumerable source, int index, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction @@ -41,6 +42,7 @@ public static partial class ValueReadOnlyCollectionExtensions _ => ValueEnumerableExtensions.ElementAtAt(source, index, predicate) }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option ElementAt(this TEnumerable source, int index, TSelector selector) where TEnumerable : IValueReadOnlyCollection @@ -55,6 +57,7 @@ public static partial class ValueReadOnlyCollectionExtensions }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option ElementAtAt(this TEnumerable source, int index, TSelector selector) where TEnumerable : IValueReadOnlyCollection @@ -68,6 +71,7 @@ public static partial class ValueReadOnlyCollectionExtensions : Option.None }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option ElementAt(this TEnumerable source, int index, TPredicate predicate, TSelector selector) where TEnumerable : IValueReadOnlyCollection diff --git a/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ValueReadOnlyList.cs new file mode 100644 index 000000000..736663171 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAt.ValueReadOnlyList.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Option ElementAt(this TEnumerable source, int index) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => source switch + { + {Count: 0} => Option.None, + _ => index < source.Count + ? ValueEnumerableExtensions.ElementAt(source, index) + : Option.None + }; + } +} diff --git a/NetFabric.Hyperlinq/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.cs similarity index 85% rename from NetFabric.Hyperlinq/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.cs index f1c13b773..c073a15ea 100644 --- a/NetFabric.Hyperlinq/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Element/ElementAt/ElementAtAsync.AsyncValueEnumerable.cs @@ -35,16 +35,17 @@ static async ValueTask> ExecuteAsync(TEnumerable source, int ind } - static ValueTask> ElementAtAsync(this TEnumerable source, int index, TPredicate predicate, CancellationToken cancellationToken) + + static ValueTask> ElementAtAsync(this TEnumerable source, int index, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction { return index < 0 ? new ValueTask>(Option.None) - : ExecuteAsync(source, index, predicate, cancellationToken); + : ExecuteAsync(source, index, cancellationToken, predicate); - static async ValueTask> ExecuteAsync(TEnumerable source, int index, TPredicate predicate, CancellationToken cancellationToken) + static async ValueTask> ExecuteAsync(TEnumerable source, int index, CancellationToken cancellationToken, TPredicate predicate) { var enumerator = source.GetAsyncEnumerator(cancellationToken); try @@ -64,16 +65,17 @@ static async ValueTask> ExecuteAsync(TEnumerable source, int ind } - static ValueTask> ElementAtAtAsync(this TEnumerable source, int index, TPredicate predicate, CancellationToken cancellationToken) + + static ValueTask> ElementAtAtAsync(this TEnumerable source, int index, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction { return index < 0 ? new ValueTask>(Option.None) - : ExecuteAsync(source, index, predicate, cancellationToken); + : ExecuteAsync(source, index, cancellationToken, predicate); - static async ValueTask> ExecuteAsync(TEnumerable source, int index, TPredicate predicate, CancellationToken cancellationToken) + static async ValueTask> ExecuteAsync(TEnumerable source, int index, CancellationToken cancellationToken, TPredicate predicate) { var enumerator = source.GetAsyncEnumerator(cancellationToken); try @@ -96,16 +98,17 @@ static async ValueTask> ExecuteAsync(TEnumerable source, int ind } - static ValueTask> ElementAtAsync(this TEnumerable source, int index, TSelector selector, CancellationToken cancellationToken) + + static ValueTask> ElementAtAsync(this TEnumerable source, int index, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction { return index < 0 ? new ValueTask>(Option.None) - : ExecuteAsync(source, index, selector, cancellationToken); + : ExecuteAsync(source, index, cancellationToken, selector); - static async ValueTask> ExecuteAsync(TEnumerable source, int index, TSelector selector, CancellationToken cancellationToken) + static async ValueTask> ExecuteAsync(TEnumerable source, int index, CancellationToken cancellationToken, TSelector selector) { var enumerator = source.GetAsyncEnumerator(cancellationToken); try @@ -125,16 +128,17 @@ static async ValueTask> ExecuteAsync(TEnumerable source, int ind } - static ValueTask> ElementAtAtAsync(this TEnumerable source, int index, TSelector selector, CancellationToken cancellationToken) + + static ValueTask> ElementAtAtAsync(this TEnumerable source, int index, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction { return index < 0 ? new ValueTask>(Option.None) - : ExecuteAsync(source, index, selector, cancellationToken); + : ExecuteAsync(source, index, cancellationToken, selector); - static async ValueTask> ExecuteAsync(TEnumerable source, int index, TSelector selector, CancellationToken cancellationToken) + static async ValueTask> ExecuteAsync(TEnumerable source, int index, CancellationToken cancellationToken, TSelector selector) { var enumerator = source.GetAsyncEnumerator(cancellationToken); try @@ -157,7 +161,8 @@ static async ValueTask> ExecuteAsync(TEnumerable source, int ind } - static ValueTask> ElementAtAsync(this TEnumerable source, int index, TPredicate predicate, TSelector selector, CancellationToken cancellationToken) + + static ValueTask> ElementAtAsync(this TEnumerable source, int index, CancellationToken cancellationToken, TPredicate predicate, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction @@ -165,9 +170,9 @@ static async ValueTask> ExecuteAsync(TEnumerable source, int ind { return index < 0 ? new ValueTask>(Option.None) - : ExecuteAsync(source, index, predicate, selector, cancellationToken); + : ExecuteAsync(source, index, cancellationToken, predicate, selector); - static async ValueTask> ExecuteAsync(TEnumerable source, int index, TPredicate predicate, TSelector selector, CancellationToken cancellationToken) + static async ValueTask> ExecuteAsync(TEnumerable source, int index, CancellationToken cancellationToken, TPredicate predicate, TSelector selector) { var enumerator = source.GetAsyncEnumerator(cancellationToken); try diff --git a/NetFabric.Hyperlinq.Core/Element/First/First.ReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Element/First/First.ReadOnlyList.cs new file mode 100644 index 000000000..d2aa13217 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Element/First/First.ReadOnlyList.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ReadOnlyListExtensions + { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static Option First(this TList source) + where TList : struct, IReadOnlyList + => source switch + { + { Count: 0 } => Option.None, + _ => Option.Some(source[0]) + }; + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Option First(this TList source, TSelector selector) + where TList : struct, IReadOnlyList + where TSelector : struct, IFunction + => source switch + { + { Count: 0 } => Option.None, + _ => Option.Some(selector.Invoke(source[0])), + }; + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Option FirstAt(this TList source, TSelector selector) + where TList : struct, IReadOnlyList + where TSelector : struct, IFunction + => source switch + { + { Count: 0 } => Option.None, + _ => Option.Some(selector.Invoke(source[0], 0)), + }; + } +} diff --git a/NetFabric.Hyperlinq/Element/First/First.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Element/First/First.ReadOnlySpan.cs similarity index 95% rename from NetFabric.Hyperlinq/Element/First/First.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Element/First/First.ReadOnlySpan.cs index 2b0c768dd..830e8f082 100644 --- a/NetFabric.Hyperlinq/Element/First/First.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Element/First/First.ReadOnlySpan.cs @@ -5,15 +5,16 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Option First(this ReadOnlySpan source) + static Option First(this ReadOnlySpan source) => source switch { { Length: 0 } => Option.None, _ => Option.Some(source[0]) }; + static Option First(this ReadOnlySpan source, TPredicate predicate) where TPredicate : struct, IFunction { @@ -26,7 +27,8 @@ public static Option First(this ReadOnlySpan source) return Option.None; } - + + static Option FirstAt(this ReadOnlySpan source, TPredicate predicate) where TPredicate : struct, IFunction { @@ -39,7 +41,8 @@ public static Option First(this ReadOnlySpan source) return Option.None; } - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option First(this ReadOnlySpan source, TSelector selector) where TSelector : struct, IFunction @@ -49,7 +52,8 @@ public static Option First(this ReadOnlySpan source) _ => Option.Some(selector.Invoke(source[0])), }; - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option FirstAt(this ReadOnlySpan source, TSelector selector) where TSelector : struct, IFunction @@ -59,7 +63,8 @@ public static Option First(this ReadOnlySpan source) _ => Option.Some(selector.Invoke(source[0], 0)), }; - + + static Option First(this ReadOnlySpan source, TPredicate predicate, TSelector selector) where TPredicate : struct, IFunction where TSelector : struct, IFunction diff --git a/NetFabric.Hyperlinq/Element/First/First.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Element/First/First.ValueEnumerable.cs similarity index 97% rename from NetFabric.Hyperlinq/Element/First/First.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Element/First/First.ValueEnumerable.cs index c6684cf86..95379dea5 100644 --- a/NetFabric.Hyperlinq/Element/First/First.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Element/First/First.ValueEnumerable.cs @@ -1,6 +1,4 @@ -using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { @@ -19,7 +17,8 @@ public static partial class ValueEnumerableExtensions }; } - + + internal static Option First(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -36,7 +35,8 @@ public static partial class ValueEnumerableExtensions return Option.None; } - + + internal static Option FirstAt(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -55,7 +55,8 @@ public static partial class ValueEnumerableExtensions return Option.None; } - + + internal static Option First(this TEnumerable source, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -69,7 +70,8 @@ public static partial class ValueEnumerableExtensions }; } - + + internal static Option FirstAt(this TEnumerable source, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -83,7 +85,8 @@ public static partial class ValueEnumerableExtensions }; } - + + internal static Option First(this TEnumerable source, TPredicate predicate, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator diff --git a/NetFabric.Hyperlinq/Element/First/First.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Element/First/First.ValueReadOnlyCollection.cs similarity index 97% rename from NetFabric.Hyperlinq/Element/First/First.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Element/First/First.ValueReadOnlyCollection.cs index 9dfb7ee6a..dcdd30bba 100644 --- a/NetFabric.Hyperlinq/Element/First/First.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Element/First/First.ValueReadOnlyCollection.cs @@ -20,11 +20,12 @@ public static partial class ValueReadOnlyCollectionExtensions static Option GetFirst(TEnumerable source) { using var enumerator = source.GetEnumerator(); - enumerator.MoveNext(); + _ = enumerator.MoveNext(); return Option.Some(enumerator.Current); } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option First(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection @@ -36,6 +37,7 @@ static Option GetFirst(TEnumerable source) _ => ValueEnumerableExtensions.First(source, predicate) }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option FirstAt(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection @@ -47,6 +49,7 @@ static Option GetFirst(TEnumerable source) _ => ValueEnumerableExtensions.FirstAt(source, predicate) }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option First(this TEnumerable source, TSelector selector) where TEnumerable : IValueReadOnlyCollection @@ -62,12 +65,13 @@ static Option GetFirst(TEnumerable source) static Option GetFirst(TEnumerable source, TSelector selector) { using var enumerator = source.GetEnumerator(); - enumerator.MoveNext(); + _ = enumerator.MoveNext(); return Option.Some(selector.Invoke(enumerator.Current)); } } - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option FirstAt(this TEnumerable source, TSelector selector) where TEnumerable : IValueReadOnlyCollection @@ -83,11 +87,12 @@ static Option GetFirst(TEnumerable source, TSelector selector) static Option GetFirst(TEnumerable source, TSelector selector) { using var enumerator = source.GetEnumerator(); - enumerator.MoveNext(); + _ = enumerator.MoveNext(); return Option.Some(selector.Invoke(enumerator.Current, 0)); } } - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option First(this TEnumerable source, TPredicate predicate, TSelector selector) diff --git a/NetFabric.Hyperlinq.Core/Element/First/First.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Element/First/First.ValueReadOnlyList.cs new file mode 100644 index 000000000..19488681e --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Element/First/First.ValueReadOnlyList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Option First(this TEnumerable source) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.First(source); + } +} diff --git a/NetFabric.Hyperlinq/Element/First/FirstAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Element/First/FirstAsync.AsyncValueEnumerable.cs similarity index 93% rename from NetFabric.Hyperlinq/Element/First/FirstAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Element/First/FirstAsync.AsyncValueEnumerable.cs index 630cdb85c..2216e721e 100644 --- a/NetFabric.Hyperlinq/Element/First/FirstAsync.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Element/First/FirstAsync.AsyncValueEnumerable.cs @@ -27,8 +27,9 @@ public static partial class AsyncValueEnumerableExtensions } } - - static async ValueTask> FirstAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + + + static async ValueTask> FirstAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction @@ -50,8 +51,9 @@ public static partial class AsyncValueEnumerableExtensions } } - - static async ValueTask> FirstAtAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + + + static async ValueTask> FirstAtAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction @@ -76,9 +78,10 @@ public static partial class AsyncValueEnumerableExtensions } } - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> FirstAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken) + static async ValueTask> FirstAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction @@ -98,9 +101,10 @@ public static partial class AsyncValueEnumerableExtensions } } - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> FirstAtAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken) + static async ValueTask> FirstAtAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction @@ -120,8 +124,9 @@ public static partial class AsyncValueEnumerableExtensions } } - - static async ValueTask> FirstAsync(this TEnumerable source, TPredicate predicate, TSelector selector, CancellationToken cancellationToken) + + + static async ValueTask> FirstAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction diff --git a/NetFabric.Hyperlinq.Core/Element/Single/Single.ReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Element/Single/Single.ReadOnlyList.cs new file mode 100644 index 000000000..45d81b242 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Element/Single/Single.ReadOnlyList.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; + +namespace NetFabric.Hyperlinq +{ + public static partial class ReadOnlyListExtensions + { + + + static Option Single(this TList source) + where TList : struct, IReadOnlyList + => source switch + { + { Count: 1 } => Option.Some(source[0]), + _ => Option.None, + }; + + + internal static Option Single(this TList source, TSelector selector) + where TList : struct, IReadOnlyList + where TSelector : struct, IFunction + => source switch + { + { Count: 1 } => Option.Some(selector.Invoke(source[0])), + _ => Option.None, + }; + + + + internal static Option SingleAt(this TList source, TSelector selector) + where TList : struct, IReadOnlyList + where TSelector : struct, IFunction + => source switch + { + { Count: 1 } => Option.Some(selector.Invoke(source[0], 0)), + _ => Option.None, + }; + } +} diff --git a/NetFabric.Hyperlinq/Element/Single/Single.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Element/Single/Single.ReadOnlySpan.cs similarity index 94% rename from NetFabric.Hyperlinq/Element/Single/Single.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Element/Single/Single.ReadOnlySpan.cs index b37218f35..4042a258f 100644 --- a/NetFabric.Hyperlinq/Element/Single/Single.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Element/Single/Single.ReadOnlySpan.cs @@ -1,13 +1,11 @@ using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - public static Option Single(this ReadOnlySpan source) + static Option Single(this ReadOnlySpan source) => source switch { { Length: 1 } => Option.Some(source[0]), @@ -35,7 +33,7 @@ public static Option Single(this ReadOnlySpan source) return Option.None; } - + static Option SingleAt(this ReadOnlySpan source, TPredicate predicate) where TPredicate : struct, IFunction { @@ -57,7 +55,7 @@ public static Option Single(this ReadOnlySpan source) return Option.None; } - + static Option Single(this ReadOnlySpan source, TSelector selector) where TSelector : struct, IFunction => source switch @@ -66,7 +64,7 @@ public static Option Single(this ReadOnlySpan source) _ => Option.None, }; - + static Option SingleAt(this ReadOnlySpan source, TSelector selector) where TSelector : struct, IFunction => source switch @@ -75,7 +73,8 @@ public static Option Single(this ReadOnlySpan source) _ => Option.None, }; - + + static Option Single(this ReadOnlySpan source, TPredicate predicate, TSelector selector) where TPredicate : struct, IFunction where TSelector : struct, IFunction diff --git a/NetFabric.Hyperlinq/Element/Single/Single.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Element/Single/Single.ValueEnumerable.cs similarity index 98% rename from NetFabric.Hyperlinq/Element/Single/Single.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Element/Single/Single.ValueEnumerable.cs index cd2d44e63..ae7ac435c 100644 --- a/NetFabric.Hyperlinq/Element/Single/Single.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Element/Single/Single.ValueEnumerable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -13,7 +12,8 @@ public static partial class ValueEnumerableExtensions where TEnumerator : struct, IEnumerator => source.GetSingle(); - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Option Single(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable @@ -21,7 +21,8 @@ public static partial class ValueEnumerableExtensions where TPredicate : struct, IFunction => source.GetSingle(predicate); - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Option SingleAt(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable @@ -29,7 +30,8 @@ public static partial class ValueEnumerableExtensions where TPredicate : struct, IFunction => source.GetSingleAt(predicate); - + + static Option Single(this TEnumerable source, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -38,7 +40,8 @@ public static partial class ValueEnumerableExtensions .GetSingle() .Select(selector); - + + static Option SingleAt(this TEnumerable source, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -60,6 +63,7 @@ public TResult Invoke(TSource item) => selector.Invoke(item, 0); } + internal static Option Single(this TEnumerable source, TPredicate predicate, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -70,7 +74,8 @@ public TResult Invoke(TSource item) //////////////////////////////// // GetSingle - + + static Option GetSingle(this TEnumerable source) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -87,7 +92,8 @@ public TResult Invoke(TSource item) return Option.None; } - + + static Option GetSingle(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -113,7 +119,8 @@ public TResult Invoke(TSource item) return Option.None; } - + + static Option GetSingleAt(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator diff --git a/NetFabric.Hyperlinq/Element/Single/Single.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Element/Single/Single.ValueReadOnlyCollection.cs similarity index 99% rename from NetFabric.Hyperlinq/Element/Single/Single.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Element/Single/Single.ValueReadOnlyCollection.cs index e42091551..899a89bd4 100644 --- a/NetFabric.Hyperlinq/Element/Single/Single.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Element/Single/Single.ValueReadOnlyCollection.cs @@ -25,6 +25,7 @@ static Option GetSingle(TEnumerable source) } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option Single(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection @@ -36,6 +37,7 @@ static Option GetSingle(TEnumerable source) _ => ValueEnumerableExtensions.Single(source, predicate) }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option SingleAt(this TEnumerable source, TPredicate predicate) where TEnumerable : IValueReadOnlyCollection @@ -47,6 +49,7 @@ static Option GetSingle(TEnumerable source) _ => ValueEnumerableExtensions.SingleAt(source, predicate) }; + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option Single(this TEnumerable source, TSelector selector) where TEnumerable : IValueReadOnlyCollection @@ -67,6 +70,7 @@ static Option GetSingle(TEnumerable source, TSelector selector) } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option SingleAt(this TEnumerable source, TSelector selector) where TEnumerable : IValueReadOnlyCollection @@ -86,7 +90,8 @@ static Option GetSingle(TEnumerable source, TSelector selector) return Option.Some(selector.Invoke(enumerator.Current, 0)); } } - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] static Option Single(this TEnumerable source, TPredicate predicate, TSelector selector) diff --git a/NetFabric.Hyperlinq.Core/Element/Single/Single.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Element/Single/Single.ValueReadOnlyList.cs new file mode 100644 index 000000000..49e6dd264 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Element/Single/Single.ValueReadOnlyList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Option Single(this TEnumerable source) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.Single(source); + } +} diff --git a/NetFabric.Hyperlinq/Element/Single/SingleAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Element/Single/SingleAsync.AsyncValueEnumerable.cs similarity index 87% rename from NetFabric.Hyperlinq/Element/Single/SingleAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Element/Single/SingleAsync.AsyncValueEnumerable.cs index 2f0b15eaf..1b46d236d 100644 --- a/NetFabric.Hyperlinq/Element/Single/SingleAsync.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Element/Single/SingleAsync.AsyncValueEnumerable.cs @@ -14,25 +14,28 @@ public static partial class AsyncValueEnumerableExtensions where TEnumerator : struct, IAsyncEnumerator => source.GetSingleAsync(cancellationToken); - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static ValueTask> SingleAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken = default) + static ValueTask> SingleAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction - => source.GetSingleAsync(predicate, cancellationToken); + => source.GetSingleAsync(cancellationToken, predicate); + + - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static ValueTask> SingleAtAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken = default) + static ValueTask> SingleAtAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction - => source.GetSingleAtAsync(predicate, cancellationToken); + => source.GetSingleAtAsync(cancellationToken, predicate); + + - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> SingleAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken = default) + static async ValueTask> SingleAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction @@ -41,9 +44,10 @@ public static partial class AsyncValueEnumerableExtensions return await option.SelectAsync(selector, cancellationToken).ConfigureAwait(false); } - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> SingleAtAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken = default) + static async ValueTask> SingleAtAsync(this TEnumerable source, CancellationToken cancellationToken, TSelector selector = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction @@ -65,21 +69,23 @@ public ValueTask InvokeAsync(TSource item, CancellationToken cancellati => selector.InvokeAsync(item, 0, cancellationToken); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static async ValueTask> SingleAsync(this TEnumerable source, TPredicate predicate, TSelector selector, CancellationToken cancellationToken = default) + static async ValueTask> SingleAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate, TSelector selector = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction where TSelector : struct, IAsyncFunction { - var option = await source.GetSingleAsync(predicate, cancellationToken).ConfigureAwait(false); + var option = await source.GetSingleAsync(cancellationToken, predicate).ConfigureAwait(false); return await option.SelectAsync(selector, cancellationToken).ConfigureAwait(false); } ///////////////////////// // GetSingleAsync - + + static async ValueTask> GetSingleAsync(this TEnumerable source, CancellationToken cancellationToken) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator @@ -87,11 +93,15 @@ public ValueTask InvokeAsync(TSource item, CancellationToken cancellati var enumerator = source.GetAsyncEnumerator(cancellationToken); try { - return await enumerator.MoveNextAsync().ConfigureAwait(false) - ? await enumerator.MoveNextAsync().ConfigureAwait(false) - ? Option.None - : Option.Some(enumerator.Current) - : Option.None; + if (!await enumerator.MoveNextAsync().ConfigureAwait(false)) + return Option.None; + + var value = enumerator.Current; + + if (await enumerator.MoveNextAsync().ConfigureAwait(false)) + return Option.None; + + return Option.Some(value); } finally { @@ -99,8 +109,7 @@ public ValueTask InvokeAsync(TSource item, CancellationToken cancellati } } - - static async ValueTask> GetSingleAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + static async ValueTask> GetSingleAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction @@ -133,8 +142,9 @@ public ValueTask InvokeAsync(TSource item, CancellationToken cancellati } } - - static async ValueTask> GetSingleAtAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) + + + static async ValueTask> GetSingleAtAsync(this TEnumerable source, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction diff --git a/NetFabric.Hyperlinq/Equality/SequenceEqual/SequenceEqual.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Equality/SequenceEqual/SequenceEqual.ReadOnlySpan.cs similarity index 83% rename from NetFabric.Hyperlinq/Equality/SequenceEqual/SequenceEqual.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Equality/SequenceEqual/SequenceEqual.ReadOnlySpan.cs index 9ae09241a..6b6a86359 100644 --- a/NetFabric.Hyperlinq/Equality/SequenceEqual/SequenceEqual.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Equality/SequenceEqual/SequenceEqual.ReadOnlySpan.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Text; namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - public static bool SequenceEqual(this ReadOnlySpan first, TEnumerable second, IEqualityComparer? comparer = null) + + static bool SequenceEqual(this ReadOnlySpan first, TEnumerable second, IEqualityComparer? comparer = default) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator { @@ -25,12 +24,12 @@ public static partial class ArrayExtensions if (firstEnded) return true; - if (comparer.Equals(enumerator.Current, enumerator.Current)) + if (comparer.Equals(first[index], enumerator.Current)) return false; } } - //public static bool SequenceEqual(this ReadOnlySpan first, TEnumerable second, IEqualityComparer? comparer = null) + //public static bool SequenceEqual(this ReadOnlySpan first, TEnumerable second, IEqualityComparer? comparer = default) // where TEnumerable : IValueReadOnlyList // where TEnumerator : struct, IEnumerator //{ diff --git a/NetFabric.Hyperlinq/Filtering/Where/Where.ArraySegment.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ArraySegment.cs similarity index 66% rename from NetFabric.Hyperlinq/Filtering/Where/Where.ArraySegment.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ArraySegment.cs index 1f40a70ee..15df2b3f2 100644 --- a/NetFabric.Hyperlinq/Filtering/Where/Where.ArraySegment.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ArraySegment.cs @@ -10,13 +10,13 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] + [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereEnumerable> Where(this in ArraySegment source, Func predicate) + static ArraySegmentWhereEnumerable> Where(this in ArraySegment source, Func predicate) => source.Where(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereEnumerable Where(this in ArraySegment source, TPredicate predicate = default) + static ArraySegmentWhereEnumerable Where(this in ArraySegment source, TPredicate predicate = default) where TPredicate : struct, IFunction => new(source, predicate); @@ -31,14 +31,17 @@ public static partial class ArrayExtensions internal ArraySegmentWhereEnumerable(in ArraySegment source, TPredicate predicate) => (this.source, this.predicate) = (source, predicate); - public readonly WhereEnumerator GetEnumerator() + public WhereEnumerator GetEnumerator() => new(source.AsSpan(), predicate); - readonly Enumerator IValueEnumerable.GetEnumerator() + + Enumerator IValueEnumerable.GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -47,7 +50,9 @@ public struct Enumerator : IEnumerator { readonly TSource[]? source; +#pragma warning disable IDE0044 // Add readonly modifier TPredicate predicate; +#pragma warning restore IDE0044 // Add readonly modifier readonly int end; int index; @@ -73,10 +78,14 @@ internal Enumerator(in ArraySegmentWhereEnumerable enumerab [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { + var index = this.index; while (++index <= end) { if (predicate.Invoke(source![index])) + { + this.index = index; return true; + } } return false; } @@ -85,61 +94,79 @@ public bool MoveNext() public readonly void Reset() => throw new NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Count() - => ((ReadOnlySpan)source.AsSpan()).Count(predicate); + => source.AsReadOnlySpan().Count(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => Count(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.AsReadOnlySpan().Count(new PredicatePredicateCombination(this.predicate, predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => CountAt(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.AsReadOnlySpan().CountAt(new PredicatePredicateAtCombination(this.predicate, predicate)); #endregion #region Quantifier [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All() - => ((ReadOnlySpan)source.AsSpan()).All(predicate); + => source.AsReadOnlySpan().All(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All(Func predicate) => All(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).All(new PredicatePredicateCombination(this.predicate, predicate)); + => source.AsReadOnlySpan().All(new PredicatePredicateCombination(this.predicate, predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All(Func predicate) => AllAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).AllAt(new PredicatePredicateAtCombination(this.predicate, predicate)); + => source.AsReadOnlySpan().AllAt(new PredicatePredicateAtCombination(this.predicate, predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any() - => ((ReadOnlySpan)source.AsSpan()).Any(predicate); + => source.AsReadOnlySpan().Any(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any(Func predicate) => Any(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).Any(new PredicatePredicateCombination(this.predicate, predicate)); + => source.AsReadOnlySpan().Any(new PredicatePredicateCombination(this.predicate, predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any(Func predicate) => AnyAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).AnyAt(new PredicatePredicateAtCombination(this.predicate, predicate)); + => source.AsReadOnlySpan().AnyAt(new PredicatePredicateAtCombination(this.predicate, predicate)); #endregion #region Filtering @@ -155,7 +182,7 @@ public bool AnyAt(TPredicate2 predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArraySegmentWhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); + => WhereAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArraySegmentWhereAtEnumerable> WhereAt(TPredicate2 predicate = default) @@ -179,16 +206,16 @@ public bool AnyAt(TPredicate2 predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option ElementAt(int index) - => ((ReadOnlySpan)source.AsSpan()).ElementAt(index, predicate); + => source.AsReadOnlySpan().ElementAt(index, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option First() - => ((ReadOnlySpan)source.AsSpan()).First(predicate); + => source.AsReadOnlySpan().First(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option Single() #pragma warning disable HLQ005 // Avoid Single() and SingleOrDefault() - => ((ReadOnlySpan)source.AsSpan()).Single(predicate); + => source.AsReadOnlySpan().Single(predicate); #pragma warning restore HLQ005 // Avoid Single() and SingleOrDefault() #endregion @@ -196,26 +223,26 @@ public Option Single() [MethodImpl(MethodImplOptions.AggressiveInlining)] public TSource[] ToArray() - => ((ReadOnlySpan)source.AsSpan()).ToArray(predicate); + => source.AsReadOnlySpan().ToArray(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => ((ReadOnlySpan)source.AsSpan()).ToArray(predicate, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ((ReadOnlySpan)source.AsSpan()).ToArray(pool, clearOnDispose, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List ToList() - => ((ReadOnlySpan)source.AsSpan()).ToList(predicate); + => source.AsReadOnlySpan().ToList(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); + => ToDictionary(new FunctionWrapper(keySelector), comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) where TKey : notnull where TKeySelector : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).ToDictionary(keySelector, comparer, predicate); + => source.AsReadOnlySpan().ToDictionary(keySelector, comparer, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) @@ -227,7 +254,7 @@ public List ToList() where TKey : notnull where TKeySelector : struct, IFunction where TElementSelector : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).ToDictionary(keySelector, elementSelector, comparer, predicate); + => source.AsReadOnlySpan().ToDictionary(keySelector, elementSelector, comparer, predicate); #endregion } @@ -235,52 +262,72 @@ public List ToList() [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this ArraySegmentWhereEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate); + => source.source.AsReadOnlySpan().Sum(source.predicate); } } diff --git a/NetFabric.Hyperlinq/Filtering/Where/Where.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.AsyncValueEnumerable.cs similarity index 58% rename from NetFabric.Hyperlinq/Filtering/Where/Where.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.AsyncValueEnumerable.cs index 5d6770b94..62c36eeaf 100644 --- a/NetFabric.Hyperlinq/Filtering/Where/Where.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.AsyncValueEnumerable.cs @@ -12,13 +12,6 @@ namespace NetFabric.Hyperlinq public static partial class AsyncValueEnumerableExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.AsyncFunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereEnumerable> Where(this TEnumerable source, Func> predicate) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - => source.Where>(new AsyncFunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static WhereEnumerable Where(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IAsyncValueEnumerable @@ -33,8 +26,8 @@ public static partial class AsyncValueEnumerableExtensions where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction { - readonly TEnumerable source; - readonly TPredicate predicate; + internal readonly TEnumerable source; + internal readonly TPredicate predicate; internal WhereEnumerable(in TEnumerable source, TPredicate predicate) { @@ -44,9 +37,10 @@ internal WhereEnumerable(in TEnumerable source, TPredicate predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this, cancellationToken); @@ -55,15 +49,18 @@ public struct Enumerator : IAsyncEnumerator , IAsyncStateMachine { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; TPredicate predicate; +#pragma warning restore IDE0044 // Add readonly modifier readonly CancellationToken cancellationToken; int state; AsyncValueTaskMethodBuilder builder; +#pragma warning disable IDE1006 // Naming Styles bool s__1; bool s__2; +#pragma warning restore IDE1006 // Naming Styles ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__2; @@ -105,7 +102,7 @@ public ValueTask MoveNextAsync() return builder.Task; } - public ValueTask DisposeAsync() + public readonly ValueTask DisposeAsync() => enumerator.DisposeAsync(); void IAsyncStateMachine.MoveNext() @@ -192,7 +189,7 @@ void IAsyncStateMachine.MoveNext() builder.SetResult(result); } - void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) + readonly void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { } } @@ -201,6 +198,16 @@ void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask CountAsync(CancellationToken cancellationToken = default) => source.CountAsync(predicate, cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask CountAsync(TPredicate2 predicate = default, CancellationToken cancellationToken = default) + where TPredicate2 : struct, IAsyncFunction + => source.CountAsync>(new AsyncPredicatePredicateCombination(this.predicate, predicate), cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask CountAtAsync(TPredicate2 predicate = default, CancellationToken cancellationToken = default) + where TPredicate2 : struct, IAsyncFunction + => source.CountAtAsync>(new AsyncPredicatePredicateAtCombination(this.predicate, predicate), cancellationToken); #endregion #region Quantifier @@ -210,20 +217,12 @@ public ValueTask AllAsync(CancellationToken cancellationToken = default) => source.AllAsync(predicate, cancellationToken); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AllAsync(Func> predicate, CancellationToken cancellationToken = default) - => AllAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AllAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) + public ValueTask AllAsync(TPredicate2 predicate = default, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction => source.AllAsync>(new AsyncPredicatePredicateCombination(this.predicate, predicate), cancellationToken); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AllAsync(Func> predicate, CancellationToken cancellationToken = default) - => AllAtAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AllAtAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) + public ValueTask AllAtAsync(TPredicate2 predicate = default, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction => source.AllAtAsync>(new AsyncPredicatePredicateAtCombination(this.predicate, predicate), cancellationToken); @@ -232,30 +231,18 @@ public ValueTask AnyAsync(CancellationToken cancellationToken = default) => source.AnyAsync(predicate, cancellationToken); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AnyAsync(Func> predicate, CancellationToken cancellationToken = default) - => AnyAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AnyAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) + public ValueTask AnyAsync(TPredicate2 predicate = default, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction => source.AnyAsync>(new AsyncPredicatePredicateCombination(this.predicate, predicate), cancellationToken); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AnyAsync(Func> predicate, CancellationToken cancellationToken = default) - => AnyAtAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AnyAtAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) + public ValueTask AnyAtAsync(TPredicate2 predicate = default, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction => source.AnyAtAsync>(new AsyncPredicatePredicateAtCombination(this.predicate, predicate), cancellationToken); #endregion #region Projection - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable> Select(Func> selector) - => Select>(new AsyncFunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereSelectEnumerable Select(TSelector selector = default) where TSelector : struct, IAsyncFunction @@ -264,18 +251,10 @@ public ValueTask AnyAtAsync(TPredicate2 predicate, Cancellati #endregion #region Filtering - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereEnumerable, TSource>> Where(Func> predicate) - => Where(new AsyncFunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereEnumerable> Where(TPredicate2 predicate = default) where TPredicate2 : struct, IAsyncFunction => source.Where>(new AsyncPredicatePredicateCombination(this.predicate, predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TSource>> Where(Func> predicate) - => WhereAt(new AsyncFunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereAtEnumerable> WhereAt(TPredicate2 predicate = default) @@ -287,58 +266,146 @@ public ValueTask AnyAtAsync(TPredicate2 predicate, Cancellati [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ElementAtAsync(int index, CancellationToken cancellationToken = default) - => source.ElementAtAsync(index, predicate, cancellationToken); + => source.ElementAtAsync(index, cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> FirstAsync(CancellationToken cancellationToken = default) - => source.FirstAsync(predicate, cancellationToken); + => source.FirstAsync(cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> SingleAsync(CancellationToken cancellationToken = default) - => source.SingleAsync(predicate, cancellationToken); + => source.SingleAsync(cancellationToken, predicate); #endregion #region Conversion [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask ToArrayAsync(CancellationToken cancellationToken = default) - => source.ToArrayAsync(predicate, cancellationToken); + => source.ToArrayAsync(cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToArrayAsync(MemoryPool pool, CancellationToken cancellationToken = default) - => source.ToArrayAsync(predicate, pool, cancellationToken); + public ValueTask> ToArrayAsync(ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) + => source.ToArrayAsync(pool, clearOnDispose, cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToListAsync(CancellationToken cancellationToken = default) - => source.ToListAsync(predicate, cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(Func> keySelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) - where TKey : notnull - => ToDictionaryAsync>(new AsyncFunctionWrapper(keySelector), comparer, cancellationToken); + => source.ToListAsync(cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToDictionaryAsync(TKeySelector keySelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) where TKey : notnull where TKeySelector : struct, IAsyncFunction - => source.ToDictionaryAsync(keySelector, comparer, predicate, cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(Func> keySelector, Func> elementSelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) - where TKey : notnull - => ToDictionaryAsync, AsyncFunctionWrapper>(new AsyncFunctionWrapper(keySelector), new AsyncFunctionWrapper(elementSelector), comparer, cancellationToken); + => source.ToDictionaryAsync(keySelector, comparer, cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToDictionaryAsync(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) where TKey : notnull where TKeySelector : struct, IAsyncFunction where TElementSelector : struct, IAsyncFunction - => source.ToDictionaryAsync(keySelector, elementSelector, comparer, predicate, cancellationToken); + => source.ToDictionaryAsync(keySelector, elementSelector, comparer, cancellationToken, predicate); #endregion } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate); } } diff --git a/NetFabric.Hyperlinq/Filtering/Where/Where.ReadOnlyMemory.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ReadOnlyMemory.cs similarity index 77% rename from NetFabric.Hyperlinq/Filtering/Where/Where.ReadOnlyMemory.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ReadOnlyMemory.cs index fde4eba10..bc3a4da78 100644 --- a/NetFabric.Hyperlinq/Filtering/Where/Where.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ReadOnlyMemory.cs @@ -10,13 +10,13 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] + [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemoryWhereEnumerable> Where(this ReadOnlyMemory source, Func predicate) + static MemoryWhereEnumerable> Where(this ReadOnlyMemory source, Func predicate) => source.Where(new FunctionWrapper(predicate)); - + [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemoryWhereEnumerable Where(this ReadOnlyMemory source, TPredicate predicate = default) + static MemoryWhereEnumerable Where(this ReadOnlyMemory source, TPredicate predicate = default) where TPredicate : struct, IFunction => new(source, predicate); @@ -31,14 +31,17 @@ public static partial class ArrayExtensions internal MemoryWhereEnumerable(ReadOnlyMemory source, TPredicate predicate) => (this.source, this.predicate) = (source, predicate); - public readonly WhereEnumerator GetEnumerator() + public WhereEnumerator GetEnumerator() => new(source.Span, predicate); - readonly Enumerator IValueEnumerable.GetEnumerator() + + Enumerator IValueEnumerable.GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -47,7 +50,9 @@ public struct Enumerator : IEnumerator { readonly ReadOnlyMemory source; +#pragma warning disable IDE0044 // Add readonly modifier TPredicate predicate; +#pragma warning restore IDE0044 // Add readonly modifier int index; internal Enumerator(in MemoryWhereEnumerable enumerable) @@ -72,11 +77,15 @@ internal Enumerator(in MemoryWhereEnumerable enumerable) public bool MoveNext() { var span = source.Span; + var index = this.index; while (++index < span.Length) { var item = span[index]; if (predicate.Invoke(item)) + { + this.index = index; return true; + } } return false; } @@ -85,14 +94,33 @@ public bool MoveNext() public readonly void Reset() => throw new NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation + [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Count() => source.Span.Count(predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => Count(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.Span.Count(new PredicatePredicateCombination(this.predicate, predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => CountAt(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.Span.CountAt(new PredicatePredicateAtCombination(this.predicate, predicate)); + #endregion #region Quantifier @@ -106,7 +134,7 @@ public bool All(Func predicate) => All(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Span.All(new PredicatePredicateCombination(this.predicate, predicate)); @@ -115,7 +143,7 @@ public bool All(Func predicate) => AllAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Span.AllAt(new PredicatePredicateAtCombination(this.predicate, predicate)); @@ -128,7 +156,7 @@ public bool Any(Func predicate) => Any(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Span.Any(new PredicatePredicateCombination(this.predicate, predicate)); @@ -137,7 +165,7 @@ public bool Any(Func predicate) => AnyAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Span.AnyAt(new PredicatePredicateAtCombination(this.predicate, predicate)); @@ -155,7 +183,7 @@ public bool AnyAt(TPredicate2 predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] public MemoryWhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); + => WhereAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public MemoryWhereAtEnumerable> WhereAt(TPredicate2 predicate = default) @@ -192,8 +220,8 @@ public Option Single() public TSource[] ToArray() => source.Span.ToArray(predicate); - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.Span.ToArray(predicate, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.Span.ToArray(pool, clearOnDispose, predicate); public List ToList() => source.Span.ToList(predicate); @@ -201,7 +229,7 @@ public List ToList() [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); + => ToDictionary(new FunctionWrapper(keySelector), comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) @@ -222,28 +250,6 @@ public List ToList() => source.Span.ToDictionary(keySelector, elementSelector, comparer, predicate); #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -256,6 +262,26 @@ public static int Sum(this MemoryWhereEnumerable s where TPredicate : struct, IFunction => source.source.Span.Sum(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemoryWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.Span.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemoryWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.Span.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemoryWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.Span.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemoryWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.Span.Sum(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this MemoryWhereEnumerable source) where TPredicate : struct, IFunction diff --git a/NetFabric.Hyperlinq/Filtering/Where/Where.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ReadOnlySpan.cs similarity index 77% rename from NetFabric.Hyperlinq/Filtering/Where/Where.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ReadOnlySpan.cs index 54640b020..2f3334d28 100644 --- a/NetFabric.Hyperlinq/Filtering/Where/Where.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ReadOnlySpan.cs @@ -9,13 +9,12 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereEnumerable> Where(this ReadOnlySpan source, Func predicate) + static SpanWhereEnumerable> Where(this ReadOnlySpan source, Func predicate) => source.Where(new FunctionWrapper(predicate)); - + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereEnumerable Where(this ReadOnlySpan source, TPredicate predicate = default) + static SpanWhereEnumerable Where(this ReadOnlySpan source, TPredicate predicate = default) where TPredicate : struct, IFunction => new(source, predicate); @@ -32,14 +31,33 @@ internal SpanWhereEnumerable(ReadOnlySpan source, TPredicate predicate) this.predicate = predicate; } - public readonly WhereEnumerator GetEnumerator() + public WhereEnumerator GetEnumerator() => new(source, predicate); - + #region Aggregation + [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Count() => source.Count(predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => Count(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.Count(new PredicatePredicateCombination(this.predicate, predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => CountAt(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.CountAt(new PredicatePredicateAtCombination(this.predicate, predicate)); + #endregion #region Quantifier @@ -52,7 +70,7 @@ public bool All(Func predicate) => All(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.All(new PredicatePredicateCombination(this.predicate, predicate)); @@ -61,7 +79,7 @@ public bool All(Func predicate) => AllAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AllAt(new PredicatePredicateAtCombination(this.predicate, predicate)); @@ -74,7 +92,7 @@ public bool Any(Func predicate) => Any(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Any(new PredicatePredicateCombination(this.predicate, predicate)); @@ -83,7 +101,7 @@ public bool Any(Func predicate) => AnyAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AnyAt(new PredicatePredicateAtCombination(this.predicate, predicate)); @@ -101,7 +119,7 @@ public bool AnyAt(TPredicate2 predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanWhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); + => WhereAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanWhereAtEnumerable> WhereAt(TPredicate2 predicate = default) @@ -138,8 +156,8 @@ public Option Single() public TSource[] ToArray() => source.ToArray(predicate); - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.ToArray(predicate, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArray(pool, clearOnDispose, predicate); public List ToList() => source.ToList(predicate); @@ -147,13 +165,13 @@ public List ToList() [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); + => ToDictionary(new FunctionWrapper(keySelector), comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) where TKey : notnull where TKeySelector : struct, IFunction - => source.ToDictionary(keySelector, comparer, predicate); + => source.ToDictionary(keySelector, comparer, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) @@ -169,7 +187,7 @@ public List ToList() #endregion - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) + public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) { comparer ??= EqualityComparer.Default; @@ -202,6 +220,26 @@ public static int Sum(this SpanWhereEnumerable sou where TPredicate : struct, IFunction => source.source.Sum(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanWhereEnumerable source) + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this SpanWhereEnumerable source) where TPredicate : struct, IFunction diff --git a/NetFabric.Hyperlinq/Filtering/Where/Where.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ValueEnumerable.cs similarity index 51% rename from NetFabric.Hyperlinq/Filtering/Where/Where.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ValueEnumerable.cs index 164dd19b6..a7ce272bd 100644 --- a/NetFabric.Hyperlinq/Filtering/Where/Where.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ValueEnumerable.cs @@ -11,13 +11,6 @@ namespace NetFabric.Hyperlinq public static partial class ValueEnumerableExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereEnumerable> Where(this TEnumerable source, Func predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source.Where>(new FunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static WhereEnumerable Where(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueEnumerable @@ -25,6 +18,7 @@ public static partial class ValueEnumerableExtensions where TPredicate : struct, IFunction => new(in source, predicate); + //[GeneratorBindings(source: "source", sourceImplements: "IValueEnumerable`2", extraTypeParameters: "TPredicate", extraParameters: "predicate")] [StructLayout(LayoutKind.Auto)] public readonly partial struct WhereEnumerable : IValueEnumerable.Enumerator> @@ -39,12 +33,14 @@ internal WhereEnumerable(in TEnumerable source, TPredicate predicate) => (this.source, this.predicate) = (source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -52,9 +48,10 @@ internal WhereEnumerable(in TEnumerable source, TPredicate predicate) public struct Enumerator : IEnumerator { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; TPredicate predicate; +#pragma warning restore IDE0044 // Add readonly modifier internal Enumerator(in WhereEnumerable enumerable) { @@ -85,10 +82,11 @@ public bool MoveNext() } [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); - public void Dispose() + public void Dispose() => enumerator.Dispose(); } @@ -98,6 +96,50 @@ public void Dispose() public int Count() => source.Count(predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.Count>(new PredicatePredicateCombination(this.predicate, predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.CountAt>(new PredicatePredicateAtCombination(this.predicate, predicate)); + + #endregion + #region Conversion + + public WhereEnumerable AsValueEnumerable() + => this; + + public WhereEnumerable AsEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TSource[] ToArray() + => source.ToArray(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArray(pool, clearOnDispose, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public List ToList() + => source.ToList(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + => source.ToDictionary(keySelector, comparer, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + where TElementSelector : struct, IFunction + => source.ToDictionary(keySelector, elementSelector, comparer, predicate); + #endregion #region Quantifier @@ -106,20 +148,12 @@ public bool All() => source.All(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.All>(new PredicatePredicateCombination(this.predicate, predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AllAt>(new PredicatePredicateAtCombination(this.predicate, predicate)); @@ -128,56 +162,36 @@ public bool Any() => source.Any(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Any>(new PredicatePredicateCombination(this.predicate, predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AnyAt>(new PredicatePredicateAtCombination(this.predicate, predicate)); #endregion #region Filtering - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereEnumerable, TSource>> Where(Func predicate) - => Where(new FunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereEnumerable> Where(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Where>(new PredicatePredicateCombination(this.predicate, predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereAtEnumerable> WhereAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.WhereAt>(new PredicatePredicateAtCombination(this.predicate, predicate)); - + #endregion #region Projection - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereSelectEnumerable Select(TSelector selector = default) where TSelector : struct, IFunction => source.WhereSelect(predicate, selector); - + #endregion #region Element @@ -194,117 +208,107 @@ public Option Single() #pragma warning disable HLQ005 // Avoid Single() and SingleOrDefault() => source.Single(predicate); #pragma warning restore HLQ005 // Avoid Single() and SingleOrDefault() - + #endregion - #region Conversion + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TSource[] ToArray() - => source.ToArray(predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.ToArray(predicate, memoryPool); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.ToList(predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => source.ToDictionary(keySelector, comparer, predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => source.ToDictionary(keySelector, elementSelector, comparer, predicate); - - #endregion - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static int Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, int, int, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static int Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, int?, int, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static long Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, long, long, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static long Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, long?, long, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static float Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, float, float, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static float Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, float?, float, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static double Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, double, double, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static double Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, double?, double, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static decimal Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, decimal, decimal, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static decimal Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, decimal?, decimal, TPredicate>(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.Sum(source.predicate); } } diff --git a/NetFabric.Hyperlinq/Filtering/Where/Where.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ValueReadOnlyCollection.cs similarity index 51% rename from NetFabric.Hyperlinq/Filtering/Where/Where.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ValueReadOnlyCollection.cs index b4638e7ad..6e4022ee0 100644 --- a/NetFabric.Hyperlinq/Filtering/Where/Where.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ValueReadOnlyCollection.cs @@ -11,13 +11,6 @@ namespace NetFabric.Hyperlinq public static partial class ValueReadOnlyCollectionExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereEnumerable> Where(this TEnumerable source, Func predicate) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => Where>(source, new FunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static WhereEnumerable Where(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueReadOnlyCollection @@ -39,12 +32,14 @@ internal WhereEnumerable(in TEnumerable source, TPredicate predicate) => (this.source, this.predicate) = (source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -52,9 +47,10 @@ internal WhereEnumerable(in TEnumerable source, TPredicate predicate) public struct Enumerator : IEnumerator { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; TPredicate predicate; +#pragma warning restore IDE0044 // Add readonly modifier internal Enumerator(in WhereEnumerable enumerable) { @@ -85,6 +81,7 @@ public bool MoveNext() } [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); @@ -98,6 +95,16 @@ public void Dispose() public int Count() => ValueReadOnlyCollectionExtensions.Count(source, predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.Count>(source, new PredicatePredicateCombination(this.predicate, predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.CountAt>(source, new PredicatePredicateAtCombination(this.predicate, predicate)); + #endregion #region Quantifier @@ -106,20 +113,12 @@ public bool All() => ValueReadOnlyCollectionExtensions.All(source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => ValueReadOnlyCollectionExtensions.All>(source, new PredicatePredicateCombination(this.predicate, predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => ValueReadOnlyCollectionExtensions.AllAt>(source, new PredicatePredicateAtCombination(this.predicate, predicate)); @@ -128,39 +127,23 @@ public bool Any() => ValueReadOnlyCollectionExtensions.Any(source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => ValueReadOnlyCollectionExtensions.Any>(source, new PredicatePredicateCombination(this.predicate, predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => ValueReadOnlyCollectionExtensions.AnyAt>(source, new PredicatePredicateAtCombination(this.predicate, predicate)); #endregion #region Filtering - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereEnumerable, TSource>> Where(Func predicate) - => Where(new FunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereEnumerable> Where(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => ValueReadOnlyCollectionExtensions.Where>(source, new PredicatePredicateCombination(this.predicate, predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereAtEnumerable> WhereAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction @@ -169,14 +152,10 @@ public bool AnyAt(TPredicate2 predicate) #endregion #region Projection - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereSelectEnumerable Select(TSelector selector = default) where TSelector : struct, IFunction - => ValueReadOnlyCollectionExtensions.WhereSelect(source, predicate, selector); + => WhereSelect(source, predicate, selector); #endregion #region Element @@ -203,29 +182,19 @@ public TSource[] ToArray() => ValueReadOnlyCollectionExtensions.ToArray(source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => ValueReadOnlyCollectionExtensions.ToArray(source, predicate, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ValueReadOnlyCollectionExtensions.ToArray(source, pool, clearOnDispose, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List ToList() => ValueReadOnlyCollectionExtensions.ToList(source, predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary(new FunctionWrapper(keySelector), comparer); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) where TKey : notnull where TKeySelector : struct, IFunction => ValueReadOnlyCollectionExtensions.ToDictionary(source, keySelector, comparer, predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) where TKey : notnull @@ -236,75 +205,103 @@ public List ToList() #endregion } - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static int Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, int, int, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static int Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, int?, int, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static long Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, long, long, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static long Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, long?, long, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static float Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, float, float, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static float Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, float?, float, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static double Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, double, double, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static double Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, double?, double, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static decimal Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, decimal, decimal, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static decimal Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, decimal?, decimal, TPredicate>(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => Sum(source.source, source.predicate); } } diff --git a/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ValueReadOnlyList.cs new file mode 100644 index 000000000..15759c6ba --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/Where.ValueReadOnlyList.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueReadOnlyCollectionExtensions.WhereEnumerable Where(this TEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.Where(source, predicate); + } +} + diff --git a/NetFabric.Hyperlinq/Filtering/Where/WhereEnumerator.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/Where/WhereEnumerator.cs similarity index 100% rename from NetFabric.Hyperlinq/Filtering/Where/WhereEnumerator.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/Where/WhereEnumerator.cs diff --git a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ArraySegment.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ArraySegment.cs similarity index 65% rename from NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ArraySegment.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ArraySegment.cs index c95b9229c..545773f06 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ArraySegment.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ArraySegment.cs @@ -10,13 +10,12 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereAtEnumerable> Where(this in ArraySegment source, Func predicate) + static ArraySegmentWhereAtEnumerable> Where(this in ArraySegment source, Func predicate) => source.WhereAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereAtEnumerable WhereAt(this in ArraySegment source, TPredicate predicate = default) + static ArraySegmentWhereAtEnumerable WhereAt(this in ArraySegment source, TPredicate predicate = default) where TPredicate : struct, IFunction => new(source, predicate); @@ -35,14 +34,17 @@ internal ArraySegmentWhereAtEnumerable(in ArraySegment source, TPredica } - public readonly WhereAtEnumerator GetEnumerator() + public WhereAtEnumerator GetEnumerator() => new(source.AsSpan(), predicate); - readonly Enumerator IValueEnumerable.GetEnumerator() + + Enumerator IValueEnumerable.GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -51,7 +53,9 @@ public struct Enumerator : IEnumerator { readonly TSource[]? source; +#pragma warning disable IDE0044 // Add readonly modifier TPredicate predicate; +#pragma warning restore IDE0044 // Add readonly modifier readonly int offset; readonly int end; int index; @@ -79,10 +83,14 @@ internal Enumerator(in ArraySegmentWhereAtEnumerable enumer [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { + var index = this.index; while (++index <= end) { if (predicate.Invoke(source![index + offset], index)) + { + this.index = index; return true; + } } return false; } @@ -91,14 +99,32 @@ public bool MoveNext() public readonly void Reset() => throw new NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Count() - => ((ReadOnlySpan)source.AsSpan()).CountAt(predicate); + => source.AsReadOnlySpan().CountAt(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => Count(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.AsReadOnlySpan().CountAt(new PredicatePredicateAtCombination(predicate, this.predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => CountAt(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.AsReadOnlySpan().CountAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); #endregion #region Quantifier @@ -106,47 +132,47 @@ public int Count() [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All() - => ((ReadOnlySpan)source.AsSpan()).AllAt(predicate); + => source.AsReadOnlySpan().AllAt(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All(Func predicate) => All(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).AllAt(new PredicatePredicateAtCombination(predicate, this.predicate)); + => source.AsReadOnlySpan().AllAt(new PredicatePredicateAtCombination(predicate, this.predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All(Func predicate) => AllAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).AllAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); + => source.AsReadOnlySpan().AllAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any() - => ((ReadOnlySpan)source.AsSpan()).AnyAt(predicate); + => source.AsReadOnlySpan().AnyAt(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any(Func predicate) => Any(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).AnyAt(new PredicatePredicateAtCombination(predicate, this.predicate)); + => source.AsReadOnlySpan().AnyAt(new PredicatePredicateAtCombination(predicate, this.predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any(Func predicate) => AnyAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).AnyAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); + => source.AsReadOnlySpan().AnyAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); #endregion #region Filtering @@ -162,7 +188,7 @@ public bool AnyAt(TPredicate2 predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArraySegmentWhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); + => WhereAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArraySegmentWhereAtEnumerable> WhereAt(TPredicate2 predicate = default) @@ -177,16 +203,16 @@ public bool AnyAt(TPredicate2 predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option ElementAt(int index) - => ((ReadOnlySpan)source.AsSpan()).ElementAtAt(index, predicate); + => source.AsReadOnlySpan().ElementAtAt(index, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option First() - => ((ReadOnlySpan)source.AsSpan()).FirstAt(predicate); + => source.AsReadOnlySpan().FirstAt(predicate); #pragma warning disable HLQ005 // Avoid Single() and SingleOrDefault() [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option Single() - => ((ReadOnlySpan)source.AsSpan()).SingleAt(predicate); + => source.AsReadOnlySpan().SingleAt(predicate); #pragma warning restore HLQ005 // Avoid Single() and SingleOrDefault() #endregion @@ -194,26 +220,26 @@ public Option Single() [MethodImpl(MethodImplOptions.AggressiveInlining)] public TSource[] ToArray() - => ((ReadOnlySpan)source.AsSpan()).ToArrayAt(predicate); + => source.AsReadOnlySpan().ToArrayAt(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => ((ReadOnlySpan)source.AsSpan()).ToArrayAt(predicate, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ((ReadOnlySpan)source.AsSpan()).ToArrayAt(pool, clearOnDispose, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List ToList() - => ((ReadOnlySpan)source.AsSpan()).ToListAt(predicate); + => source.AsReadOnlySpan().ToListAt(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); + => ToDictionary(new FunctionWrapper(keySelector), comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) where TKey : notnull where TKeySelector : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).ToDictionaryAt(keySelector, comparer, predicate); + => source.AsReadOnlySpan().ToDictionaryAt(keySelector, comparer, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) @@ -225,7 +251,7 @@ public List ToList() where TKey : notnull where TKeySelector : struct, IFunction where TElementSelector : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).ToDictionaryAt(keySelector, elementSelector, comparer, predicate); + => source.AsReadOnlySpan().ToDictionaryAt(keySelector, elementSelector, comparer, predicate); #endregion } @@ -233,52 +259,72 @@ public List ToList() [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.AsReadOnlySpan().SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.AsReadOnlySpan().SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.AsReadOnlySpan().SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.AsReadOnlySpan().SumAt(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this ArraySegmentWhereAtEnumerable source) where TPredicate : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.predicate); + => source.source.AsReadOnlySpan().SumAt(source.predicate); } } diff --git a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.AsyncValueEnumerable.cs similarity index 58% rename from NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.AsyncValueEnumerable.cs index 7b0ecfc5e..2c01b55c3 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.AsyncValueEnumerable.cs @@ -12,13 +12,6 @@ namespace NetFabric.Hyperlinq public static partial class AsyncValueEnumerableExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.AsyncFunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereAtEnumerable> Where(this TEnumerable source, Func> predicate) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - => source.WhereAt>(new AsyncFunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static WhereAtEnumerable WhereAt(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IAsyncValueEnumerable @@ -33,8 +26,8 @@ public static partial class AsyncValueEnumerableExtensions where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction { - readonly TEnumerable source; - readonly TPredicate predicate; + internal readonly TEnumerable source; + internal readonly TPredicate predicate; internal WhereAtEnumerable(in TEnumerable source, TPredicate predicate) { @@ -44,9 +37,10 @@ internal WhereAtEnumerable(in TEnumerable source, TPredicate predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this, cancellationToken); @@ -55,16 +49,19 @@ public struct Enumerator : IAsyncEnumerator , IAsyncStateMachine { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; TPredicate predicate; +#pragma warning restore IDE0044 // Add readonly modifier readonly CancellationToken cancellationToken; int index; int state; AsyncValueTaskMethodBuilder builder; +#pragma warning disable IDE1006 // Naming Styles bool s__1; bool s__2; +#pragma warning restore IDE1006 // Naming Styles ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__2; @@ -194,7 +191,7 @@ void IAsyncStateMachine.MoveNext() builder.SetResult(result); } - void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) + readonly void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { } } @@ -204,6 +201,16 @@ void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) public ValueTask CountAsync(CancellationToken cancellationToken = default) => source.CountAtAsync(predicate, cancellationToken); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask CountAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) + where TPredicate2 : struct, IAsyncFunction + => source.CountAtAsync>(new AsyncPredicatePredicateAtCombination(predicate, this.predicate), cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask CountAtAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) + where TPredicate2 : struct, IAsyncFunction + => source.CountAtAsync>(new AsyncPredicateAtPredicateAtCombination(this.predicate, predicate), cancellationToken); + #endregion #region Quantifier @@ -211,19 +218,11 @@ public ValueTask CountAsync(CancellationToken cancellationToken = default) public ValueTask AllAsync(CancellationToken cancellationToken = default) => source.AllAtAsync(predicate, cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AllAsync(Func> predicate, CancellationToken cancellationToken = default) - => AllAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AllAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction => source.AllAtAsync>(new AsyncPredicatePredicateAtCombination(predicate, this.predicate), cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AllAsync(Func> predicate, CancellationToken cancellationToken = default) - => AllAtAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AllAtAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction @@ -233,19 +232,11 @@ public ValueTask AllAtAsync(TPredicate2 predicate, Cancellati public ValueTask AnyAsync(CancellationToken cancellationToken = default) => source.AnyAtAsync(predicate, cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AnyAsync(Func> predicate, CancellationToken cancellationToken = default) - => AnyAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AnyAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction => source.AnyAtAsync>(new AsyncPredicatePredicateAtCombination(predicate, this.predicate), cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AnyAsync(Func> predicate, CancellationToken cancellationToken = default) - => AnyAtAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AnyAtAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction @@ -257,18 +248,10 @@ public ValueTask AnyAtAsync(TPredicate2 predicate, Cancellati #endregion #region Filtering - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TPredicate, TSource>> Where(Func> predicate) - => Where(new AsyncFunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereAtEnumerable> Where(TPredicate2 predicate = default) where TPredicate2 : struct, IAsyncFunction => source.WhereAt>(new AsyncPredicatePredicateAtCombination(predicate, this.predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TSource>> Where(Func> predicate) - => WhereAt(new AsyncFunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereAtEnumerable> WhereAt(TPredicate2 predicate = default) @@ -280,58 +263,146 @@ public ValueTask AnyAtAsync(TPredicate2 predicate, Cancellati [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ElementAtAsync(int index, CancellationToken cancellationToken = default) - => source.ElementAtAtAsync(index, predicate, cancellationToken); + => source.ElementAtAtAsync(index, cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> FirstAsync(CancellationToken cancellationToken = default) - => source.FirstAtAsync(predicate, cancellationToken); + => source.FirstAtAsync(cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> SingleAsync(CancellationToken cancellationToken = default) - => source.SingleAtAsync(predicate, cancellationToken); + => source.SingleAtAsync(cancellationToken, predicate); #endregion #region Conversion [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask ToArrayAsync(CancellationToken cancellationToken = default) - => source.ToArrayAtAsync(predicate, cancellationToken); + => source.ToArrayAtAsync(cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToArrayAsync(MemoryPool pool, CancellationToken cancellationToken = default) - => source.ToArrayAtAsync(predicate, pool, cancellationToken); + public ValueTask> ToArrayAsync(ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) + => source.ToArrayAtAsync(pool, clearOnDispose, cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToListAsync(CancellationToken cancellationToken = default) - => source.ToListAtAsync(predicate, cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(Func> keySelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) - where TKey : notnull - => ToDictionaryAsync>(new AsyncFunctionWrapper(keySelector), comparer, cancellationToken); + => source.ToListAtAsync(cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToDictionaryAsync(TKeySelector keySelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) where TKey : notnull where TKeySelector : struct, IAsyncFunction - => source.ToDictionaryAtAsync(keySelector, comparer, predicate, cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(Func> keySelector, Func> elementSelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) - where TKey : notnull - => ToDictionaryAsync, AsyncFunctionWrapper>(new AsyncFunctionWrapper(keySelector), new AsyncFunctionWrapper(elementSelector), comparer, cancellationToken); + => source.ToDictionaryAtAsync(keySelector, comparer, cancellationToken, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToDictionaryAsync(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) where TKey : notnull where TKeySelector : struct, IAsyncFunction where TElementSelector : struct, IAsyncFunction - => source.ToDictionaryAtAsync(keySelector, elementSelector, comparer, predicate, cancellationToken); + => source.ToDictionaryAtAsync(keySelector, elementSelector, comparer, cancellationToken, predicate); #endregion } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.predicate); } } diff --git a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ReadOnlyMemory.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ReadOnlyMemory.cs similarity index 78% rename from NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ReadOnlyMemory.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ReadOnlyMemory.cs index 517a440b3..a08a106c6 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ReadOnlyMemory.cs @@ -11,13 +11,12 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemoryWhereAtEnumerable> Where(this ReadOnlyMemory source, Func predicate) + static MemoryWhereAtEnumerable> Where(this ReadOnlyMemory source, Func predicate) => source.WhereAt(new FunctionWrapper(predicate)); - + [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemoryWhereAtEnumerable WhereAt(this ReadOnlyMemory source, TPredicate predicate = default) + static MemoryWhereAtEnumerable WhereAt(this ReadOnlyMemory source, TPredicate predicate = default) where TPredicate : struct, IFunction => new(source, predicate); @@ -32,14 +31,17 @@ public static partial class ArrayExtensions internal MemoryWhereAtEnumerable(ReadOnlyMemory source, TPredicate predicate) => (this.source, this.predicate) = (source, predicate); - public readonly WhereAtEnumerator GetEnumerator() + public WhereAtEnumerator GetEnumerator() => new(source.Span, predicate); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() + + DisposableEnumerator IValueEnumerable.GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this); @@ -86,7 +88,7 @@ public bool MoveNext() public readonly void Reset() => throw new NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation @@ -94,6 +96,24 @@ public bool MoveNext() public int Count() => source.Span.CountAt(predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => Count(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.Span.CountAt(new PredicatePredicateAtCombination(predicate, this.predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => CountAt(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.Span.CountAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); + #endregion #region Quantifier @@ -106,7 +126,7 @@ public bool All(Func predicate) => All(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Span.AllAt(new PredicatePredicateAtCombination(predicate, this.predicate)); @@ -115,7 +135,7 @@ public bool All(Func predicate) => AllAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Span.AllAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); @@ -128,7 +148,7 @@ public bool Any(Func predicate) => Any(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Span.AnyAt(new PredicatePredicateAtCombination(predicate, this.predicate)); @@ -137,7 +157,7 @@ public bool Any(Func predicate) => AnyAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.Span.AnyAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); @@ -155,7 +175,7 @@ public bool AnyAt(TPredicate2 predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] public MemoryWhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); + => WhereAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public MemoryWhereAtEnumerable> WhereAt(TPredicate2 predicate = default) @@ -183,8 +203,8 @@ public Option Single() public TSource[] ToArray() => source.Span.ToArrayAt(predicate); - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.Span.ToArrayAt(predicate, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.Span.ToArrayAt(pool, clearOnDispose, predicate); public List ToList() => source.Span.ToListAt(predicate); @@ -192,7 +212,7 @@ public List ToList() [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) where TKey : notnull - => ToDictionaryAt>(new FunctionWrapper(keySelector), comparer); + => ToDictionaryAt(new FunctionWrapper(keySelector), comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionaryAt(TKeySelector keySelector, IEqualityComparer? comparer = default) @@ -213,28 +233,6 @@ public List ToList() => source.Span.ToDictionaryAt(keySelector, elementSelector, comparer, predicate); #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -247,6 +245,26 @@ public static int Sum(this MemoryWhereAtEnumerable where TPredicate : struct, IFunction => source.source.Span.SumAt(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemoryWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.Span.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemoryWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.Span.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemoryWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.Span.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemoryWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.Span.SumAt(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this MemoryWhereAtEnumerable source) where TPredicate : struct, IFunction diff --git a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ReadOnlySpan.cs similarity index 77% rename from NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ReadOnlySpan.cs index ad13e7012..c346fffda 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ReadOnlySpan.cs @@ -9,13 +9,12 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereAtEnumerable> Where(this ReadOnlySpan source, Func predicate) + static SpanWhereAtEnumerable> Where(this ReadOnlySpan source, Func predicate) => source.WhereAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereAtEnumerable WhereAt(this ReadOnlySpan source, TPredicate predicate = default) + static SpanWhereAtEnumerable WhereAt(this ReadOnlySpan source, TPredicate predicate = default) where TPredicate : struct, IFunction => new(source, predicate); @@ -32,7 +31,7 @@ internal SpanWhereAtEnumerable(ReadOnlySpan source, TPredicate predicat this.predicate = predicate; } - public readonly WhereAtEnumerator GetEnumerator() + public WhereAtEnumerator GetEnumerator() => new(source, predicate); #region Aggregation @@ -40,6 +39,24 @@ internal SpanWhereAtEnumerable(ReadOnlySpan source, TPredicate predicat public int Count() => source.CountAt(predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => Count(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.CountAt(new PredicatePredicateAtCombination(predicate, this.predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => CountAt(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.CountAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); + #endregion #region Quantifier @@ -52,7 +69,7 @@ public bool All(Func predicate) => All(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AllAt(new PredicatePredicateAtCombination(predicate, this.predicate)); @@ -61,7 +78,7 @@ public bool All(Func predicate) => AllAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AllAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); @@ -74,7 +91,7 @@ public bool Any(Func predicate) => Any(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AnyAt(new PredicatePredicateAtCombination(predicate, this.predicate)); @@ -83,7 +100,7 @@ public bool Any(Func predicate) => AnyAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AnyAt(new PredicateAtPredicateAtCombination(this.predicate, predicate)); @@ -101,7 +118,7 @@ public bool AnyAt(TPredicate2 predicate) [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanWhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); + => WhereAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanWhereAtEnumerable> WhereAt(TPredicate2 predicate = default) @@ -129,8 +146,8 @@ public Option Single() public TSource[] ToArray() => source.ToArrayAt(predicate); - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.ToArrayAt(predicate, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArrayAt(pool, clearOnDispose, predicate); public List ToList() => source.ToListAt(predicate); @@ -138,13 +155,13 @@ public List ToList() [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); + => ToDictionary(new FunctionWrapper(keySelector), comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) where TKey : notnull where TKeySelector : struct, IFunction - => source.ToDictionaryAt(keySelector, comparer, predicate); + => source.ToDictionaryAt(keySelector, comparer, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) @@ -160,7 +177,7 @@ public List ToList() #endregion - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) + public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) { comparer ??= EqualityComparer.Default; @@ -193,6 +210,26 @@ public static int Sum(this SpanWhereAtEnumerable s where TPredicate : struct, IFunction => source.source.SumAt(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanWhereAtEnumerable source) + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this SpanWhereAtEnumerable source) where TPredicate : struct, IFunction diff --git a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ValueEnumerable.cs similarity index 51% rename from NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ValueEnumerable.cs index bc3922a28..ccf932394 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ValueEnumerable.cs @@ -11,13 +11,6 @@ namespace NetFabric.Hyperlinq public static partial class ValueEnumerableExtensions { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereAtEnumerable> Where(this TEnumerable source, Func predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source.WhereAt>(new FunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static WhereAtEnumerable WhereAt(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueEnumerable @@ -39,12 +32,14 @@ internal WhereAtEnumerable(in TEnumerable source, TPredicate predicate) => (this.source, this.predicate) = (source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -52,9 +47,10 @@ internal WhereAtEnumerable(in TEnumerable source, TPredicate predicate) public struct Enumerator : IEnumerator { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; TPredicate predicate; +#pragma warning restore IDE0044 // Add readonly modifier int index; internal Enumerator(in WhereAtEnumerable enumerable) @@ -90,6 +86,7 @@ public bool MoveNext() } [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); @@ -104,6 +101,16 @@ public void Dispose() public int Count() => source.CountAt(predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.CountAt>(new PredicatePredicateAtCombination(predicate, this.predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => source.CountAt>(new PredicateAtPredicateAtCombination(this.predicate, predicate)); + #endregion #region Quantifier @@ -112,20 +119,12 @@ public bool All() => source.AllAt(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AllAt>(new PredicatePredicateAtCombination(predicate, this.predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AllAt>(new PredicateAtPredicateAtCombination(this.predicate, predicate)); @@ -134,39 +133,23 @@ public bool Any() => source.AnyAt(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AnyAt>(new PredicatePredicateAtCombination(predicate, this.predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.AnyAt>(new PredicateAtPredicateAtCombination(this.predicate, predicate)); #endregion #region Filtering - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TPredicate, TSource>> Where(Func predicate) - => Where(new FunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereAtEnumerable> Where(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction => source.WhereAt>(new PredicatePredicateAtCombination(predicate, this.predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereAtEnumerable> WhereAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction @@ -200,29 +183,19 @@ public TSource[] ToArray() => source.ToArrayAt(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.ToArrayAt(predicate, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArrayAt(pool, clearOnDispose, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List ToList() => source.ToListAt(predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionaryAt>(new FunctionWrapper(keySelector), comparer); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionaryAt(TKeySelector keySelector, IEqualityComparer? comparer = default) where TKey : notnull where TKeySelector : struct, IFunction => source.ToDictionaryAt(keySelector, comparer, predicate); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionaryAt, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionaryAt(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) where TKey : notnull @@ -233,75 +206,103 @@ public List ToList() #endregion } - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static int Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.SumAt, WhereEnumerable.Enumerator, int, int, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static int Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.SumAt, WhereEnumerable.Enumerator, int?, int, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static long Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.SumAt, WhereEnumerable.Enumerator, long, long, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static long Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.SumAt, WhereEnumerable.Enumerator, long?, long, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static float Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, float, float, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static float Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.SumAt, WhereEnumerable.Enumerator, float?, float, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static double Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, double, double, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static double Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.SumAt, WhereEnumerable.Enumerator, double?, double, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static decimal Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.SumAt, WhereEnumerable.Enumerator, decimal, decimal, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static decimal Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.SumAt, WhereEnumerable.Enumerator, decimal?, decimal, TPredicate>(source.predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => source.source.SumAt(source.predicate); } } diff --git a/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ValueReadOnlyCollection.cs new file mode 100644 index 000000000..686e5fffe --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ValueReadOnlyCollection.cs @@ -0,0 +1,307 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyCollectionExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static WhereAtEnumerable WhereAt(this TEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => new(in source, predicate); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct WhereAtEnumerable + : IValueEnumerable.Enumerator> + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + { + internal readonly TEnumerable source; + internal readonly TPredicate predicate; + + internal WhereAtEnumerable(in TEnumerable source, TPredicate predicate) + => (this.source, this.predicate) = (source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + => new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; + TPredicate predicate; +#pragma warning restore IDE0044 // Add readonly modifier + int index; + + internal Enumerator(in WhereAtEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + predicate = enumerable.predicate; + index = -1; + } + + public readonly TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => enumerator.Current; + } + readonly TSource IEnumerator.Current + => enumerator.Current; + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => enumerator.Current; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + checked + { + while (enumerator.MoveNext()) + { + if (predicate.Invoke(enumerator.Current, ++index)) + return true; + } + } + return false; + } + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public void Dispose() + => enumerator.Dispose(); + } + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => CountAt(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.CountAt>(source, new PredicatePredicateAtCombination(predicate, this.predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.CountAt>(source, new PredicateAtPredicateAtCombination(this.predicate, predicate)); + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool All() + => ValueReadOnlyCollectionExtensions.AllAt(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool All(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.AllAt>(source, new PredicatePredicateAtCombination(predicate, this.predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AllAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.AllAt>(source, new PredicateAtPredicateAtCombination(this.predicate, predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => ValueReadOnlyCollectionExtensions.AnyAt(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.AnyAt>(source, new PredicatePredicateAtCombination(predicate, this.predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AnyAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.AnyAt>(source, new PredicateAtPredicateAtCombination(this.predicate, predicate)); + + #endregion + #region Filtering + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public WhereAtEnumerable> Where(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.WhereAt>(source, new PredicatePredicateAtCombination(predicate, this.predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public WhereAtEnumerable> WhereAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.WhereAt>(source, new PredicateAtPredicateAtCombination(this.predicate, predicate)); + + #endregion + #region Projection + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => ElementAtAt(source, index, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => FirstAt(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() +#pragma warning disable HLQ005 // Avoid Single() and SingleOrDefault() + => SingleAt(source, predicate); +#pragma warning restore HLQ005 // Avoid Single() and SingleOrDefault() + + #endregion + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TSource[] ToArray() + => ToArrayAt(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ToArrayAt(source, pool, clearOnDispose, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public List ToList() + => ToListAt(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + => ToDictionaryAt(source, keySelector, comparer, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + where TElementSelector : struct, IFunction + => ToDictionaryAt(source, keySelector, elementSelector, comparer, predicate); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => SumAt(source.source, source.predicate); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ValueReadOnlyList.cs new file mode 100644 index 000000000..8d1102f04 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAt.ValueReadOnlyList.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueReadOnlyCollectionExtensions.WhereAtEnumerable WhereAt(this TEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.WhereAt(source, predicate); + } +} + diff --git a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAtEnumerator.cs b/NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAtEnumerator.cs similarity index 100% rename from NetFabric.Hyperlinq/Filtering/WhereAt/WhereAtEnumerator.cs rename to NetFabric.Hyperlinq.Core/Filtering/Where/WhereAt/WhereAtEnumerator.cs diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ArraySegment.cs b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ArraySegment.cs similarity index 60% rename from NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ArraySegment.cs rename to NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ArraySegment.cs index 42620d2a1..656f059a8 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ArraySegment.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ArraySegment.cs @@ -10,8 +10,9 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { + [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereSelectEnumerable WhereSelect( + static ArraySegmentWhereSelectEnumerable WhereSelect( this in ArraySegment source, TPredicate predicate, TSelector selector) @@ -19,7 +20,6 @@ public static partial class ArrayExtensions where TSelector : struct, IFunction => new(source, predicate, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public readonly partial struct ArraySegmentWhereSelectEnumerable : IValueEnumerable.Enumerator> @@ -34,14 +34,17 @@ internal ArraySegmentWhereSelectEnumerable(in ArraySegment source, TPre => (this.source, this.predicate, this.selector) = (source, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly WhereSelectEnumerator GetEnumerator() + public WhereSelectEnumerator GetEnumerator() => new(source.AsSpan(), predicate, selector); - readonly Enumerator IValueEnumerable.GetEnumerator() + + Enumerator IValueEnumerable.GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -50,8 +53,10 @@ public struct Enumerator : IEnumerator { readonly TSource[]? source; +#pragma warning disable IDE0044 // Add readonly modifier TPredicate predicate; TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier readonly int end; int index; @@ -64,21 +69,26 @@ internal Enumerator(in ArraySegmentWhereSelectEnumerable selector.Invoke(source![index]); - readonly TResult IEnumerator.Current - => selector.Invoke(source![index]); + public readonly TResult Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => selector.Invoke(source![index]); + } readonly object? IEnumerator.Current // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(source![index])!; + => selector.Invoke(source![index]); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { + var index = this.index; while (++index <= end) { if (predicate.Invoke(source![index])) + { + this.index = index; return true; + } } return false; } @@ -87,14 +97,32 @@ public bool MoveNext() public readonly void Reset() => throw new NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Count() - => ((ReadOnlySpan)source.AsSpan()).Count(predicate); + => source.AsReadOnlySpan().Count(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => Count(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.Count, Enumerator, TResult, TPredicate2>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => CountAt(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.CountAt, Enumerator, TResult, TPredicate2>(this, predicate); #endregion #region Quantifier @@ -102,123 +130,105 @@ public int Count() [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All() - => ((ReadOnlySpan)source.AsSpan()).All(predicate); + => source.AsReadOnlySpan().All(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All(Func predicate) => All(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.All, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.All, Enumerator, TResult, TPredicate2>(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All(Func predicate) => AllAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.AllAt, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.AllAt, Enumerator, TResult, TPredicate2>(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any() - => ((ReadOnlySpan)source.AsSpan()).Any(predicate); + => source.AsReadOnlySpan().Any(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any(Func predicate) => Any(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.Any, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.Any, Enumerator, TResult, TPredicate2>(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any(Func predicate) => AnyAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.AnyAt, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.AnyAt, Enumerator, TResult, TPredicate2>(predicate); #endregion #region Filtering [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => this.Where, ArraySegmentWhereSelectEnumerable.Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) + public ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.Where, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.Where, Enumerator, TResult, TPredicate2>(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => this.Where, ArraySegmentWhereSelectEnumerable.Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) + public ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.WhereAt, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.WhereAt, Enumerator, TResult, TPredicate2>(predicate); #endregion #region Projection - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereSelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArraySegmentWhereSelectEnumerable> Select(TSelector2 selector = default) where TSelector2 : struct, IFunction => source.WhereSelect>(predicate, new SelectorSelectorCombination(this.selector, selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) + public ValueEnumerableExtensions.SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) where TSubEnumerable : IValueEnumerable where TSubEnumerator : struct, IEnumerator where TSelector2 : struct, IFunction - => this.SelectMany, ArraySegmentWhereSelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); + => this.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); #endregion #region Element [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option ElementAt(int index) - => ((ReadOnlySpan)source.AsSpan()).ElementAt(index, predicate, selector); + => source.AsReadOnlySpan().ElementAt(index, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option First() - => ((ReadOnlySpan)source.AsSpan()).First(predicate, selector); + => source.AsReadOnlySpan().First(predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option Single() - => ((ReadOnlySpan)source.AsSpan()).Single(predicate, selector); + => source.AsReadOnlySpan().Single(predicate, selector); #endregion #region Conversion [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult[] ToArray() - => ((ReadOnlySpan)source.AsSpan()).ToArray(predicate, selector); + => source.AsReadOnlySpan().ToArray(predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => ((ReadOnlySpan)source.AsSpan()).ToArray(predicate, selector, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ((ReadOnlySpan)source.AsSpan()).ToArray(pool, clearOnDispose, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List ToList() - => ((ReadOnlySpan)source.AsSpan()).ToList(predicate, selector); + => source.AsReadOnlySpan().ToList(predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) @@ -229,7 +239,7 @@ public List ToList() public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) where TKey : notnull where TKeySelector : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).ToDictionary(keySelector, comparer, predicate, selector); + => source.AsReadOnlySpan().ToDictionary(keySelector, comparer, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) @@ -241,7 +251,7 @@ public List ToList() where TKey : notnull where TKeySelector : struct, IFunction where TElementSelector : struct, IFunction - => ((ReadOnlySpan)source.AsSpan()).ToDictionary(keySelector, elementSelector, comparer, predicate, selector); + => source.AsReadOnlySpan().ToDictionary(keySelector, elementSelector, comparer, predicate, selector); #endregion } @@ -250,61 +260,85 @@ public List ToList() public static int Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this ArraySegmentWhereSelectEnumerable source) where TPredicate : struct, IFunction where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.predicate, source.selector); + => source.source.AsReadOnlySpan().Sum(source.predicate, source.selector); } } diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.AsyncValueEnumerable.cs similarity index 54% rename from NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.AsyncValueEnumerable.cs index 8a33d3053..dd5799b49 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.AsyncValueEnumerable.cs @@ -11,6 +11,7 @@ namespace NetFabric.Hyperlinq { public static partial class AsyncValueEnumerableExtensions { + [MethodImpl(MethodImplOptions.AggressiveInlining)] static WhereSelectEnumerable WhereSelect( this TEnumerable source, @@ -22,7 +23,6 @@ public static partial class AsyncValueEnumerableExtensions where TSelector : struct, IAsyncFunction => new(in source, predicate, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public readonly partial struct WhereSelectEnumerable : IAsyncValueEnumerable.Enumerator> @@ -31,17 +31,18 @@ public static partial class AsyncValueEnumerableExtensions where TPredicate : struct, IAsyncFunction where TSelector : struct, IAsyncFunction { - readonly TEnumerable source; - readonly TPredicate predicate; - readonly TSelector selector; + internal readonly TEnumerable source; + internal readonly TPredicate predicate; + internal readonly TSelector selector; internal WhereSelectEnumerable(in TEnumerable source, TPredicate predicate, TSelector selector) => (this.source, this.predicate, this.selector) = (source, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this, cancellationToken); @@ -50,18 +51,21 @@ public struct Enumerator : IAsyncEnumerator , IAsyncStateMachine { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; TPredicate predicate; TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier readonly CancellationToken cancellationToken; int state; AsyncValueTaskMethodBuilder builder; TSource? item; +#pragma warning disable IDE1006 // Naming Styles bool s__2; TResult? s__3; bool s__4; +#pragma warning restore IDE1006 // Naming Styles ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__2; ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__3; @@ -229,6 +233,16 @@ void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) public ValueTask CountAsync(CancellationToken cancellationToken = default) => source.CountAsync(predicate, cancellationToken); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask CountAsync(TPredicate2 predicate = default, CancellationToken cancellationToken = default) + where TPredicate2 : struct, IAsyncFunction + => AsyncValueEnumerableExtensions.CountAsync, Enumerator, TResult, TPredicate2>(this, predicate, cancellationToken); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask CountAtAsync(TPredicate2 predicate = default, CancellationToken cancellationToken = default) + where TPredicate2 : struct, IAsyncFunction + => AsyncValueEnumerableExtensions.CountAtAsync, Enumerator, TResult, TPredicate2>(this, predicate, cancellationToken); + #endregion #region Quantifier @@ -236,74 +250,46 @@ public ValueTask CountAsync(CancellationToken cancellationToken = default) public ValueTask AllAsync(CancellationToken cancellationToken = default) => source.AllAsync(predicate, cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AllAsync(Func> predicate, CancellationToken cancellationToken = default) - => AllAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AllAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction - => this.AllAsync, WhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate, cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AllAsync(Func> predicate, CancellationToken cancellationToken = default) - => AllAtAsync(new AsyncFunctionWrapper(predicate), cancellationToken); + => this.AllAsync, Enumerator, TResult, TPredicate2>(predicate, cancellationToken); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AllAtAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction - => this.AllAtAsync, WhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate, cancellationToken); + => this.AllAtAsync, Enumerator, TResult, TPredicate2>(predicate, cancellationToken); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AnyAsync(CancellationToken cancellationToken = default) => source.AnyAsync(predicate, cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AnyAsync(Func> predicate, CancellationToken cancellationToken = default) - => AnyAsync(new AsyncFunctionWrapper(predicate), cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AnyAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction - => this.AnyAsync, WhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate, cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask AnyAsync(Func> predicate, CancellationToken cancellationToken = default) - => AnyAtAsync(new AsyncFunctionWrapper(predicate), cancellationToken); + => this.AnyAsync, Enumerator, TResult, TPredicate2>(predicate, cancellationToken); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AnyAtAsync(TPredicate2 predicate, CancellationToken cancellationToken = default) where TPredicate2 : struct, IAsyncFunction - => this.AnyAtAsync, WhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate, cancellationToken); + => this.AnyAtAsync, Enumerator, TResult, TPredicate2>(predicate, cancellationToken); #endregion #region Filtering [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly WhereEnumerable, WhereSelectEnumerable.Enumerator, TResult, AsyncFunctionWrapper> Where(Func> predicate) - => this.Where, WhereSelectEnumerable.Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly WhereEnumerable, WhereSelectEnumerable.Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) + public WhereEnumerable, Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) where TPredicate2 : struct, IAsyncFunction - => this.Where, WhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly WhereAtEnumerable, WhereSelectEnumerable.Enumerator, TResult, AsyncFunctionWrapper> Where(Func> predicate) - => this.Where, WhereSelectEnumerable.Enumerator, TResult>(predicate); + => this.Where, Enumerator, TResult, TPredicate2>(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly WhereAtEnumerable, WhereSelectEnumerable.Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) + public WhereAtEnumerable, Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) where TPredicate2 : struct, IAsyncFunction - => this.WhereAt, WhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.WhereAt, Enumerator, TResult, TPredicate2>(predicate); #endregion #region Projection - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable, TSource, TResult, TResult2>> Select(Func> selector) - => Select>(new AsyncFunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public WhereSelectEnumerable> Select(TSelector2 selector = default) where TSelector2 : struct, IAsyncFunction @@ -314,37 +300,32 @@ public ValueTask AnyAtAsync(TPredicate2 predicate, Cancellati [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ElementAtAsync(int index, CancellationToken cancellationToken = default) - => source.ElementAtAsync(index, predicate, selector, cancellationToken); + => source.ElementAtAsync(index, cancellationToken, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> FirstAsync(CancellationToken cancellationToken = default) - => source.FirstAsync(predicate, selector, cancellationToken); + => source.FirstAsync(cancellationToken, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> SingleAsync(CancellationToken cancellationToken = default) - => source.SingleAsync(predicate, selector, cancellationToken); + => source.SingleAsync(cancellationToken, predicate, selector); #endregion #region Conversion [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask ToArrayAsync(CancellationToken cancellationToken = default) - => source.ToArrayAsync(predicate, selector, cancellationToken); + => source.ToArrayAsync(cancellationToken, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToArrayAsync(MemoryPool pool, CancellationToken cancellationToken = default) - => source.ToArrayAsync(predicate, selector, pool, cancellationToken); + public ValueTask> ToArrayAsync(ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) + => source.ToArrayAsync(pool, clearOnDispose, cancellationToken, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToListAsync(CancellationToken cancellationToken = default) - => source.ToListAsync(predicate, selector, cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(Func> keySelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) - where TKey : notnull - => ToDictionaryAsync>(new AsyncFunctionWrapper(keySelector), comparer, cancellationToken); + => source.ToListAsync(cancellationToken, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToDictionaryAsync(TKeySelector keySelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) @@ -352,11 +333,6 @@ public ValueTask> ToListAsync(CancellationToken cancellationToken where TKeySelector : struct, IAsyncFunction => source.ToDictionaryAsync(keySelector, comparer, cancellationToken, predicate, selector); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(Func> keySelector, Func> elementSelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) - where TKey : notnull - => ToDictionaryAsync, AsyncFunctionWrapper>(new AsyncFunctionWrapper(keySelector), new AsyncFunctionWrapper(elementSelector), comparer, cancellationToken); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToDictionaryAsync(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) where TKey : notnull @@ -366,6 +342,118 @@ public ValueTask> ToListAsync(CancellationToken cancellationToken #endregion } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this WhereSelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TPredicate : struct, IAsyncFunction + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.predicate, source.selector); } } diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.cs b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ReadOnlyMemory.cs similarity index 71% rename from NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.cs rename to NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ReadOnlyMemory.cs index e0bf9c4aa..bfb1469e9 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ReadOnlyMemory.cs @@ -11,6 +11,7 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { + [MethodImpl(MethodImplOptions.AggressiveInlining)] static MemoryWhereSelectEnumerable WhereSelect( this ReadOnlyMemory source, @@ -20,7 +21,6 @@ public static partial class ArrayExtensions where TSelector : struct, IFunction => new(source, predicate, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public readonly partial struct MemoryWhereSelectEnumerable : IValueEnumerable.Enumerator> @@ -36,14 +36,17 @@ internal MemoryWhereSelectEnumerable(ReadOnlyMemory source, TPredicate [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly WhereSelectEnumerator GetEnumerator() + public WhereSelectEnumerator GetEnumerator() => new(source.Span, predicate, selector); - readonly Enumerator IValueEnumerable.GetEnumerator() + + Enumerator IValueEnumerable.GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -52,8 +55,10 @@ public struct Enumerator : IEnumerator { readonly ReadOnlyMemory source; +#pragma warning disable IDE0044 // Add readonly modifier TPredicate predicate; TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier int index; internal Enumerator(in MemoryWhereSelectEnumerable enumerable) @@ -64,14 +69,12 @@ internal Enumerator(in MemoryWhereSelectEnumerable selector.Invoke(source.Span[index]); } - readonly TResult IEnumerator.Current - => selector.Invoke(source.Span[index]); - readonly object? IEnumerator.Current + object? IEnumerator.Current // ReSharper disable once HeapView.PossibleBoxingAllocation => selector.Invoke(source.Span[index]); @@ -92,7 +95,7 @@ public bool MoveNext() public readonly void Reset() => throw new NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation @@ -101,6 +104,24 @@ public bool MoveNext() public int Count() => source.Span.Count(predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => Count(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.Count, Enumerator, TResult, TPredicate2>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(Func predicate) + => CountAt(new FunctionWrapper(predicate)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.CountAt, Enumerator, TResult, TPredicate2>(this, predicate); + #endregion #region Quantifier @@ -113,18 +134,18 @@ public bool All(Func predicate) => All(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) + public bool All(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.All, MemoryWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.All, Enumerator, TResult, TPredicate2>(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All(Func predicate) => AllAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) + public bool AllAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.AllAt, MemoryWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.AllAt, Enumerator, TResult, TPredicate2>(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any() @@ -135,64 +156,46 @@ public bool Any(Func predicate) => Any(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) + public bool Any(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.Any, MemoryWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.Any, Enumerator, TResult, TPredicate2>(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Any(Func predicate) => AnyAt(new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) + public bool AnyAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.AnyAt, MemoryWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.AnyAt, Enumerator, TResult, TPredicate2>(predicate); #endregion #region Filtering [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, MemoryWhereSelectEnumerable.Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => this.Where, MemoryWhereSelectEnumerable.Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, MemoryWhereSelectEnumerable.Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) + public ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.Where, MemoryWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.Where, Enumerator, TResult, TPredicate2>(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, MemoryWhereSelectEnumerable.Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => this.Where, MemoryWhereSelectEnumerable.Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, MemoryWhereSelectEnumerable.Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) + public ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) where TPredicate2 : struct, IFunction - => this.WhereAt, MemoryWhereSelectEnumerable.Enumerator, TResult, TPredicate2>(predicate); + => this.WhereAt, Enumerator, TResult, TPredicate2>(predicate); #endregion #region Projection - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public MemoryWhereSelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public MemoryWhereSelectEnumerable> Select(TSelector2 selector = default) where TSelector2 : struct, IFunction => source.WhereSelect>(predicate, new SelectorSelectorCombination(this.selector, selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, MemoryWhereSelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, MemoryWhereSelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, MemoryWhereSelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) + public ValueEnumerableExtensions.SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) where TSubEnumerable : IValueEnumerable where TSubEnumerator : struct, IEnumerator where TSelector2 : struct, IFunction - => this.SelectMany, MemoryWhereSelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); + => this.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); #endregion #region Element @@ -217,8 +220,8 @@ public TResult[] ToArray() => source.Span.ToArray(predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.Span.ToArray(predicate, selector, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.Span.ToArray(pool, clearOnDispose, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List ToList() @@ -227,7 +230,7 @@ public List ToList() [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); + => ToDictionary(new FunctionWrapper(keySelector), comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) @@ -248,28 +251,6 @@ public List ToList() => source.Span.ToDictionary(keySelector, elementSelector, comparer, predicate, selector); #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -284,6 +265,30 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer where TSelector : struct, IFunction => source.source.Span.Sum(source.predicate, source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemoryWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Span.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemoryWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Span.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemoryWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Span.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemoryWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Span.Sum(source.predicate, source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this MemoryWhereSelectEnumerable source) where TPredicate : struct, IFunction diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ReadOnlySpan.cs similarity index 76% rename from NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ReadOnlySpan.cs index bbcb0826c..5cbabe94b 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ReadOnlySpan.cs @@ -1,7 +1,6 @@ using System; using System.Buffers; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -10,6 +9,7 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { + [MethodImpl(MethodImplOptions.AggressiveInlining)] static SpanWhereSelectEnumerable WhereSelect( this ReadOnlySpan source, @@ -19,7 +19,6 @@ public static partial class ArrayExtensions where TSelector : struct, IFunction => new(source, predicate, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public readonly ref struct SpanWhereSelectEnumerable where TPredicate : struct, IFunction @@ -36,7 +35,7 @@ internal SpanWhereSelectEnumerable(ReadOnlySpan source, TPredicate pred this.selector = selector; } - public readonly WhereSelectEnumerator GetEnumerator() + public WhereSelectEnumerator GetEnumerator() => new(source, predicate, selector); #region Aggregation @@ -45,6 +44,24 @@ internal SpanWhereSelectEnumerable(ReadOnlySpan source, TPredicate pred public int Count() => source.Count(predicate); + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public int Count(Func predicate) + // => Count(new FunctionWrapper(predicate)); + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public int Count(TPredicate2 predicate = default) + // where TPredicate2 : struct, IFunction + // => ValueEnumerableExtensions.Count, WhereSelectEnumerator, TResult, TPredicate2>(this, predicate); + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public int Count(Func predicate) + // => CountAt(new FunctionWrapper(predicate)); + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public int CountAt(TPredicate2 predicate = default) + // where TPredicate2 : struct, IFunction + // => ValueEnumerableExtensions.CountAt, WhereSelectEnumerator, TResult, TPredicate2>(this, predicate); + #endregion #region Quantifier @@ -94,8 +111,8 @@ public TResult[] ToArray() => source.ToArray(predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.ToArray(predicate, selector, memoryPool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArray(pool, clearOnDispose, predicate, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List ToList() @@ -104,7 +121,7 @@ public List ToList() [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); + => ToDictionary(new FunctionWrapper(keySelector), comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) @@ -126,7 +143,7 @@ public List ToList() #endregion - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) + public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) { comparer ??= EqualityComparer.Default; @@ -161,6 +178,30 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer where TSelector : struct, IFunction => source.source.Sum(source.predicate, source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanWhereSelectEnumerable source) + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this SpanWhereSelectEnumerable source) where TPredicate : struct, IFunction diff --git a/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ValueEnumerable.cs new file mode 100644 index 000000000..212b14883 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ValueEnumerable.cs @@ -0,0 +1,338 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueEnumerableExtensions + { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static WhereSelectEnumerable WhereSelect( + this TEnumerable source, + TPredicate predicate, + TSelector selector) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => new(in source, predicate, selector); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct WhereSelectEnumerable + : IValueEnumerable.Enumerator> + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + { + internal readonly TEnumerable source; + internal readonly TPredicate predicate; + internal readonly TSelector selector; + + internal WhereSelectEnumerable(in TEnumerable source, TPredicate predicate, TSelector selector) + { + this.source = source; + this.predicate = predicate; + this.selector = selector; + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() => + new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; + TPredicate predicate; + TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier + + internal Enumerator(in WhereSelectEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + predicate = enumerable.predicate; + selector = enumerable.selector; + } + + public TResult Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => selector.Invoke(enumerator.Current); + } + object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => selector.Invoke(enumerator.Current); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + while (enumerator.MoveNext()) + { + if (predicate.Invoke(enumerator.Current)) + return true; + } + return false; + } + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public void Dispose() + => enumerator.Dispose(); + } + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => source.Count(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.Count, Enumerator, TResult, TPredicate2>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.CountAt, Enumerator, TResult, TPredicate2>(this, predicate); + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool All() + => source.All(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool All(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.All, Enumerator, TResult, TPredicate2>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AllAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.AllAt, Enumerator, TResult, TPredicate2>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => source.Any(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.Any, Enumerator, TResult, TPredicate2>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AnyAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.AnyAt, Enumerator, TResult, TPredicate2>(predicate); + + #endregion + #region Filtering + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public WhereEnumerable, Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.Where, Enumerator, TResult, TPredicate2>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public WhereAtEnumerable, Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.WhereAt, Enumerator, TResult, TPredicate2>(predicate); + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public WhereSelectEnumerable> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => source.WhereSelect>(predicate, new SelectorSelectorCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector2 : struct, IFunction + => this.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => source.ElementAt(index, predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => source.First(predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => source.Single(predicate, selector); + + #endregion + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TResult[] ToArray() + => source.ToArray(predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArray(pool, clearOnDispose, predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public List ToList() + => source.ToList(predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + => source.ToDictionary(keySelector, comparer, predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + where TElementSelector : struct, IFunction + => source.ToDictionary(keySelector, elementSelector, comparer, predicate, selector); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => source.source.Sum(source.predicate, source.selector); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ValueReadOnlyCollection.cs new file mode 100644 index 000000000..d163a0fce --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelect.ValueReadOnlyCollection.cs @@ -0,0 +1,338 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyCollectionExtensions + { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static WhereSelectEnumerable WhereSelect( + this TEnumerable source, + TPredicate predicate, + TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => new(in source, predicate, selector); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct WhereSelectEnumerable + : IValueEnumerable.Enumerator> + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + { + internal readonly TEnumerable source; + internal readonly TPredicate predicate; + internal readonly TSelector selector; + + internal WhereSelectEnumerable(in TEnumerable source, TPredicate predicate, TSelector selector) + { + this.source = source; + this.predicate = predicate; + this.selector = selector; + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() => + new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; + TPredicate predicate; + TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier + + internal Enumerator(in WhereSelectEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + predicate = enumerable.predicate; + selector = enumerable.selector; + } + + public TResult Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => selector.Invoke(enumerator.Current); + } + object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => selector.Invoke(enumerator.Current); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + while (enumerator.MoveNext()) + { + if (predicate.Invoke(enumerator.Current)) + return true; + } + return false; + } + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public void Dispose() + => enumerator.Dispose(); + } + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => ValueReadOnlyCollectionExtensions.Count(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.Count, Enumerator, TResult, TPredicate2>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.CountAt, Enumerator, TResult, TPredicate2>(this, predicate); + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool All() + => ValueReadOnlyCollectionExtensions.All(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool All(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.All, Enumerator, TResult, TPredicate2>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AllAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.AllAt, Enumerator, TResult, TPredicate2>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => ValueReadOnlyCollectionExtensions.Any(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.Any, Enumerator, TResult, TPredicate2>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AnyAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => this.AnyAt, Enumerator, TResult, TPredicate2>(predicate); + + #endregion + #region Filtering + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.Where, Enumerator, TResult, TPredicate2>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) + where TPredicate2 : struct, IFunction + => ValueEnumerableExtensions.WhereAt, Enumerator, TResult, TPredicate2>(this, predicate); + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public WhereSelectEnumerable> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => WhereSelect>(source, predicate, new SelectorSelectorCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector2 : struct, IFunction + => ValueEnumerableExtensions.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(this, selector); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => ValueReadOnlyCollectionExtensions.ElementAt(source, index, predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => ValueReadOnlyCollectionExtensions.First(source, predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => ValueReadOnlyCollectionExtensions.Single(source, predicate, selector); + + #endregion + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TResult[] ToArray() + => ValueReadOnlyCollectionExtensions.ToArray(source, predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ValueReadOnlyCollectionExtensions.ToArray(source, pool, clearOnDispose, predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public List ToList() + => ValueReadOnlyCollectionExtensions.ToList(source, predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.ToDictionary(source, keySelector, comparer, predicate, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) + where TKey : notnull + where TKeySelector : struct, IFunction + where TElementSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.ToDictionary(source, keySelector, elementSelector, comparer, predicate, selector); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this WhereSelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.predicate, source.selector); + } +} + diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelectEnumerator.cs b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelectEnumerator.cs similarity index 91% rename from NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelectEnumerator.cs rename to NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelectEnumerator.cs index 11e618bd0..df7f34b58 100644 --- a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelectEnumerator.cs +++ b/NetFabric.Hyperlinq.Core/Filtering/WhereSelect/WhereSelect/WhereSelectEnumerator.cs @@ -10,8 +10,10 @@ namespace NetFabric.Hyperlinq where TSelector : struct, IFunction { readonly ReadOnlySpan source; +#pragma warning disable IDE0044 // Add readonly modifier TPredicate predicate; TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier int index; internal WhereSelectEnumerator(ReadOnlySpan source, TPredicate predicate, TSelector selector) diff --git a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Empty.cs b/NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Empty.cs similarity index 68% rename from NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Empty.cs rename to NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Empty.cs index ebe85f679..bcab7773f 100644 --- a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Empty.cs +++ b/NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Empty.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -11,17 +8,12 @@ namespace NetFabric.Hyperlinq public static partial class AsyncValueEnumerable { - public static EmptyEnumerable Empty() => - EmptyEnumerable.Instance; + public static EmptyEnumerable Empty() + => new(); - public partial class EmptyEnumerable + public readonly partial struct EmptyEnumerable : IAsyncValueEnumerable.DisposableEnumerator> { - // ReSharper disable once HeapView.ObjectAllocation.Evident - public static EmptyEnumerable Instance { get; } = new(); - - EmptyEnumerable() { } - [MethodImpl(MethodImplOptions.AggressiveInlining)] #pragma warning disable IDE0060 // Remove unused parameter public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) @@ -35,25 +27,26 @@ IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(Cancellat public readonly struct Enumerator { - public readonly TSource Current + public TSource Current => default!; - public readonly ValueTask MoveNextAsync() + public ValueTask MoveNextAsync() => default; } public readonly struct DisposableEnumerator : IAsyncEnumerator { - public readonly TSource Current + public TSource Current => default!; - readonly TSource IAsyncEnumerator.Current + + TSource IAsyncEnumerator.Current => default!; - public readonly ValueTask MoveNextAsync() + public ValueTask MoveNextAsync() => default; - public readonly ValueTask DisposeAsync() + public ValueTask DisposeAsync() => default; } } diff --git a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Range.cs b/NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Range.cs similarity index 88% rename from NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Range.cs rename to NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Range.cs index 2149a5031..63f676f55 100644 --- a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Range.cs +++ b/NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Range.cs @@ -29,7 +29,6 @@ public static RangeEnumerable Range(int start, int count) return new RangeEnumerable(start, count, end); } - [GeneratorMapping("TSource", "int", true)] [StructLayout(LayoutKind.Auto)] public readonly partial struct RangeEnumerable : IAsyncValueEnumerable @@ -46,11 +45,13 @@ internal RangeEnumerable(int start, int count, int end) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator(CancellationToken cancellationToken = default) + public Enumerator GetEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly DisposableEnumerator IAsyncValueEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + DisposableEnumerator IAsyncValueEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this, cancellationToken); @@ -115,7 +116,7 @@ public ValueTask MoveNextAsync() } public readonly ValueTask DisposeAsync() - => new ValueTask(); + => new(); } #pragma warning disable IDE0060 // Remove unused parameter @@ -133,8 +134,8 @@ public ValueTask AnyAsync(CancellationToken cancellationToken = default) [MethodImpl(MethodImplOptions.AggressiveInlining)] public RangeEnumerable Skip(int count) { - var (skipCount, takeCount) = Utils.Skip(this.count, count); - return Range(start + skipCount, takeCount); + var (newOffset, newCount) = Utils.Skip(this.count, count); + return Range(start + newOffset, newCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -142,8 +143,8 @@ public RangeEnumerable Take(int count) => Range(start, Utils.Take(this.count, count)); #pragma warning disable IDE0060 // Remove unused parameter - public ValueTask ContainsAsync(int value, CancellationToken cancellationToken = default) - => new ValueTask(value >= start && value < end); + public ValueTask ContainsAsync(int value, CancellationToken cancellationToken) + => new(value >= start && value < end); #pragma warning restore IDE0060 // Remove unused parameter public ValueTask ContainsAsync(int value, IEqualityComparer? comparer, CancellationToken cancellationToken = default) @@ -185,9 +186,9 @@ public ValueTask ToArrayAsync(CancellationToken cancellationToken = defau return new ValueTask(array); } - public ValueTask> ToArrayAsync(MemoryPool pool, CancellationToken cancellationToken = default) + public ValueTask> ToArrayAsync(ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) { - var result = pool.Rent(count); + var result = pool.Lease(count, clearOnDispose); var span = result.Memory.Span; if (start is 0) { @@ -205,7 +206,7 @@ public ValueTask> ToArrayAsync(MemoryPool pool, Cancellat span[index] = index + start; } } - return new ValueTask>(result); + return new ValueTask>(result); } public async ValueTask> ToListAsync(CancellationToken cancellationToken = default) diff --git a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Repeat.cs b/NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Repeat.cs similarity index 80% rename from NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Repeat.cs rename to NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Repeat.cs index 9fc649a32..7989ab37d 100644 --- a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Repeat.cs +++ b/NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Repeat.cs @@ -31,11 +31,13 @@ internal RepeatEnumerable(TSource value, int count) => (this.value, this.count) = (value, count); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly AsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public AsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly DisposableAsyncEnumerator IAsyncValueEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + DisposableAsyncEnumerator IAsyncValueEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) // ReSharper disable once HeapView.BoxingAllocation => new DisposableAsyncEnumerator(in this, cancellationToken); @@ -54,7 +56,7 @@ internal AsyncEnumerator(in RepeatEnumerable enumerable, CancellationTo this.cancellationToken = cancellationToken; } - public readonly TSource Current { get; } + public TSource Current { get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask MoveNextAsync() @@ -80,7 +82,7 @@ internal DisposableAsyncEnumerator(in RepeatEnumerable enumerable, Canc this.cancellationToken = cancellationToken; } - public readonly TSource Current { get; } + public TSource Current { get; } readonly TSource IAsyncEnumerator.Current => Current; @@ -109,7 +111,7 @@ internal DisposableEnumerator(in RepeatEnumerable enumerable) end = counter + enumerable.count; } - public readonly TSource Current { get; } + public TSource Current { get; } readonly TSource IEnumerator.Current => Current; readonly object? IEnumerator.Current @@ -121,6 +123,7 @@ public bool MoveNext() => ++counter <= end; [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); @@ -152,10 +155,6 @@ public ValueTask ContainsAsync(TSource value, IEqualityComparer? ? new ValueTask(result: count is not 0 && EqualityComparer.Default.Equals(this.value, value)) : new ValueTask(result: count is not 0 && comparer.Equals(this.value, value)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RepeatEnumerable Select(Func> selector) - => Select>(new AsyncFunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public RepeatEnumerable Select(TSelector selector = default) where TSelector : struct, IAsyncFunction @@ -163,31 +162,28 @@ public RepeatEnumerable Select(Func ToArrayAsync(CancellationToken cancellationToken = default) { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var array = new TSource[count]; - if (value is object) + if (value is null) + return new ValueTask(result: new TSource[count]); + + var array = Utils.AllocateUninitializedArray(count); + for (var index = 0; index < array.Length; index++) { - var end = count - 1; - for (var index = 0; index <= end; index++) - { - cancellationToken.ThrowIfCancellationRequested(); - array[index] = value; - } + cancellationToken.ThrowIfCancellationRequested(); + array[index] = value; } return new ValueTask(result: array); } - public ValueTask> ToArrayAsync(MemoryPool pool, CancellationToken cancellationToken = default) + public ValueTask> ToArrayAsync(ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) { - var result = pool.RentSliced(count); + var result = pool.Lease(count, clearOnDispose); var array = result.Memory.Span; - var end = count - 1; - for (var index = 0; index <= end; index++) + for (var index = 0; index < array.Length; index++) { cancellationToken.ThrowIfCancellationRequested(); array[index] = value; } - return new ValueTask>(result: result); + return new ValueTask>(result: result); } public async ValueTask> ToListAsync(CancellationToken cancellationToken = default) diff --git a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Return.cs b/NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Return.cs similarity index 67% rename from NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Return.cs rename to NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Return.cs index 018d73662..3e936f76c 100644 --- a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Return.cs +++ b/NetFabric.Hyperlinq.Core/Generation/AsyncValueEnumerable/Return.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; @@ -24,11 +23,13 @@ internal ReturnEnumerable(TSource value) => this.value = value; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetAsyncEnumerator() + public Enumerator GetAsyncEnumerator() => new(in this); - readonly DisposableEnumerator IAsyncValueEnumerable.GetAsyncEnumerator(CancellationToken _) + + DisposableEnumerator IAsyncValueEnumerable.GetAsyncEnumerator(CancellationToken _) => new(in this); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken _) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken _) // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this); @@ -43,7 +44,7 @@ internal Enumerator(in ReturnEnumerable enumerable) moveNext = true; } - public readonly TSource Current { get; } + public TSource Current { get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask MoveNextAsync() @@ -66,7 +67,7 @@ internal DisposableEnumerator(in ReturnEnumerable enumerable) moveNext = true; } - public readonly TSource Current { get; } + public TSource Current { get; } readonly TSource IAsyncEnumerator.Current => Current; @@ -92,10 +93,6 @@ public ValueTask ContainsAsync(TSource value, IEqualityComparer? ? new ValueTask(result: EqualityComparer.Default.Equals(this.value, value)) : new ValueTask(result: comparer.Equals(this.value, value)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReturnEnumerable Select(Func> selector) - => Select>(new AsyncFunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReturnEnumerable Select(TSelector selector = default) where TSelector : struct, IAsyncFunction @@ -128,29 +125,19 @@ public ValueTask> ToListAsync() => new(result: new List(1) { value }); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionaryAsync>(new FunctionWrapper(keySelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(TKeySelector keySelector, IEqualityComparer? comparer = default) + public async ValueTask> ToDictionaryAsync(TKeySelector keySelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) where TKey : notnull - where TKeySelector : struct, IFunction + where TKeySelector : struct, IAsyncFunction // ReSharper disable once HeapView.ObjectAllocation.Evident - => new(result: new Dictionary(1, comparer) { { keySelector.Invoke(value), value } }); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionaryAsync, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); + => new Dictionary(1, comparer) { { await keySelector.InvokeAsync(value, cancellationToken).ConfigureAwait(false), value } }; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToDictionaryAsync(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) + public async ValueTask> ToDictionaryAsync(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction + where TKeySelector : struct, IAsyncFunction + where TElementSelector : struct, IAsyncFunction // ReSharper disable once HeapView.ObjectAllocation.Evident - => new(result: new Dictionary(1, comparer) { { keySelector.Invoke(value), elementSelector.Invoke(value) } }); + => new Dictionary(1, comparer) { { await keySelector.InvokeAsync(value, cancellationToken).ConfigureAwait(false), await elementSelector.InvokeAsync(value, cancellationToken).ConfigureAwait(false) } }; } #pragma warning disable IDE0060 // Remove unused parameter diff --git a/NetFabric.Hyperlinq/Generation/ValueEnumerable/CreateValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/CreateValueEnumerable.cs similarity index 81% rename from NetFabric.Hyperlinq/Generation/ValueEnumerable/CreateValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/CreateValueEnumerable.cs index 68441f2ed..9fac65d71 100644 --- a/NetFabric.Hyperlinq/Generation/ValueEnumerable/CreateValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/CreateValueEnumerable.cs @@ -11,7 +11,7 @@ public static partial class ValueEnumerable public static CreateValueEnumerable Create(Func getEnumerator) where TEnumerator : struct, IEnumerator - => new CreateValueEnumerable(getEnumerator); + => new(getEnumerator); [StructLayout(LayoutKind.Auto)] public readonly partial struct CreateValueEnumerable @@ -24,12 +24,14 @@ internal CreateValueEnumerable(Func getEnumerator) => this.getEnumerator = getEnumerator; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly TEnumerator GetEnumerator() + public TEnumerator GetEnumerator() => getEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => getEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => getEnumerator(); } diff --git a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Empty.cs b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Empty.cs similarity index 81% rename from NetFabric.Hyperlinq/Generation/ValueEnumerable/Empty.cs rename to NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Empty.cs index 03681446b..d8c935d85 100644 --- a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Empty.cs +++ b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Empty.cs @@ -12,7 +12,7 @@ public static partial class ValueEnumerable public static EmptyEnumerable Empty() => new(); - public partial struct EmptyEnumerable + public readonly partial struct EmptyEnumerable : IValueReadOnlyList.DisposableEnumerator> , IList { @@ -20,10 +20,10 @@ public int Count => 0; public TSource this[int index] - => Throw.IndexOutOfRangeException(); + => Throw.ArgumentOutOfRangeException(nameof(index)); TSource IList.this[int index] { - get => this[index]; + get => Throw.ArgumentOutOfRangeException(nameof(index)); [ExcludeFromCodeCoverage] // ReSharper disable once ValueParameterNotUsed @@ -45,11 +45,6 @@ IEnumerator IEnumerable.GetEnumerator() bool ICollection.IsReadOnly => true; - public void CopyTo(Span span) - { - // nothing to do - } - public void CopyTo(TSource[] array, int arrayIndex) { // nothing to do @@ -82,32 +77,32 @@ void IList.RemoveAt(int index) public readonly struct Enumerator { - public readonly TSource Current + public TSource Current => default!; - public readonly bool MoveNext() + public bool MoveNext() => default; } public readonly struct DisposableEnumerator : IEnumerator { - public readonly TSource Current + public TSource Current => default!; - readonly TSource IEnumerator.Current + TSource IEnumerator.Current => default!; - readonly object? IEnumerator.Current - => default!; + object? IEnumerator.Current + => default; - public readonly bool MoveNext() + public bool MoveNext() => default; [ExcludeFromCodeCoverage] - public readonly void Reset() { } + public void Reset() { } - public readonly void Dispose() { } + public void Dispose() { } } } } diff --git a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Range.cs b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Range.cs similarity index 64% rename from NetFabric.Hyperlinq/Generation/ValueEnumerable/Range.cs rename to NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Range.cs index a47b59766..2443a0670 100644 --- a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Range.cs +++ b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Range.cs @@ -2,7 +2,6 @@ using System.Buffers; using System.Collections; using System.Collections.Generic; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; @@ -18,46 +17,60 @@ public static RangeEnumerable Range(int start, int count) if (count < 0) Throw.ArgumentOutOfRangeException(nameof(count)); - var end = 0; try { - end = checked(start + count); + _ = checked(start + count); } catch (OverflowException) { Throw.ArgumentOutOfRangeException(nameof(count)); } - return new RangeEnumerable(start, end); + return new RangeEnumerable(start, count); } - [GeneratorMapping("TSource", "int", true)] [StructLayout(LayoutKind.Auto)] public readonly partial struct RangeEnumerable - : IValueReadOnlyCollection - , ICollection + : IValueReadOnlyList + , IList { readonly int start; - readonly int end; - internal RangeEnumerable(int start, int end) - => (this.start, this.end) = (start, end); + internal RangeEnumerable(int start, int count) + => (this.start, Count) = (start, count); - public readonly int Count + public int this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => end - start; + get + { + ThrowIfArgument.OutOfRange(index, Count, nameof(index)); + return index + start; + } + } + + int IList.this[int index] + { + get => this[index]; + [DoesNotReturn] + // ReSharper disable once ValueParameterNotUsed + set => Throw.NotSupportedException(); } + + public int Count { get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() + + DisposableEnumerator IValueEnumerable.GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this); @@ -74,12 +87,20 @@ public void CopyTo(Span span) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyTo(int[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); + => CopyTo(array.AsSpan(arrayIndex)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Contains(int value) - => value >= start && value < end; + => value >= start && value < start + Count; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int IndexOf(int value) + { + if (value < start || value >= start + Count) + return -1; + return value - start; + } [ExcludeFromCodeCoverage] void ICollection.Add(int item) @@ -90,28 +111,31 @@ void ICollection.Clear() [ExcludeFromCodeCoverage] bool ICollection.Remove(int item) => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + void IList.Insert(int index, int item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + void IList.RemoveAt(int index) + => Throw.NotSupportedException(); [StructLayout(LayoutKind.Auto)] public struct Enumerator { readonly int end; - int current; internal Enumerator(in RangeEnumerable enumerable) { - current = enumerable.start - 1; - end = current + enumerable.Count; + Current = enumerable.start - 1; + end = Current + enumerable.Count; } - public int Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => current; + public int Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; private set; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() - => ++current <= end; + => ++Current <= end; } [StructLayout(LayoutKind.Auto)] @@ -119,28 +143,26 @@ public struct DisposableEnumerator : IEnumerator { readonly int end; - int current; internal DisposableEnumerator(in RangeEnumerable enumerable) { - current = enumerable.start - 1; - end = current + enumerable.Count; + Current = enumerable.start - 1; + end = Current + enumerable.Count; } - public int Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => current; + public int Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; private set; } object? IEnumerator.Current // ReSharper disable once HeapView.BoxingAllocation - => current; + => Current; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() - => ++current <= end; + => ++Current <= end; [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); @@ -152,8 +174,8 @@ public bool MoveNext() [MethodImpl(MethodImplOptions.AggressiveInlining)] public RangeEnumerable Skip(int count) { - var (skipCount, takeCount) = Utils.Skip(Count, count); - return Range(start + skipCount, takeCount); + var (newOffset, newCount) = Utils.Skip(Count, count); + return Range(start + newOffset, newCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -178,7 +200,9 @@ public bool Contains(int value, IEqualityComparer? comparer) if (Count is 0) return false; - if (comparer is null || ReferenceEquals(comparer, EqualityComparer.Default)) + var end = start + Count; + + if (comparer.UseDefaultComparer()) return value >= start && value < end; for (var item = start; item < end; item++) @@ -196,18 +220,18 @@ public bool Contains(int value, IEqualityComparer? comparer) #region Projection [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RangeSelectVectorEnumerable, Vector>, FunctionWrapper> SelectVector(Func, Vector> vectorSelector, Func selector) + public RangeSelectVectorContext, Vector>, FunctionWrapper> SelectVector(Func, Vector> vectorSelector, Func selector) where TResult : struct - => ValueEnumerable.SelectVector, Vector>, FunctionWrapper>(start, Count, vectorSelector, selector); + => ValueEnumerable.SelectVector(start, Count, vectorSelector, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RangeSelectVectorEnumerable SelectVector(TSelector selector = default) + public RangeSelectVectorContext SelectVector(TSelector selector = default) where TSelector : struct, IFunction, Vector>, IFunction where TResult : struct => ValueEnumerable.SelectVector(start, Count, selector, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RangeSelectVectorEnumerable SelectVector(TVectorSelector vectorSelector = default, TSelector selector = default) + public RangeSelectVectorContext SelectVector(TVectorSelector vectorSelector = default, TSelector selector = default) where TVectorSelector : struct, IFunction, Vector> where TSelector : struct, IFunction where TResult : struct @@ -227,9 +251,9 @@ public int[] ToArray() return array; } - public IMemoryOwner ToArray(MemoryPool pool) + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) { - var result = pool.RentSliced(Count); + var result = pool.Lease(Count, clearOnDispose); ArrayExtensions.CopyRange(start, Count, result.Memory.Span); return result; } diff --git a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Repeat.cs b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Repeat.cs similarity index 86% rename from NetFabric.Hyperlinq/Generation/ValueEnumerable/Repeat.cs rename to NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Repeat.cs index 98d8d2b1b..e45ccc3f7 100644 --- a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Repeat.cs +++ b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Repeat.cs @@ -33,18 +33,21 @@ internal RepeatEnumerable(TSource value, int count) this.count = count; } - public readonly int Count + public int Count => count; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() + + DisposableEnumerator IValueEnumerable.GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this); @@ -61,7 +64,7 @@ public void CopyTo(Span span) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyTo(TSource[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); + => CopyTo(array.AsSpan(arrayIndex)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Contains(TSource item) @@ -96,7 +99,7 @@ internal Enumerator(in RepeatEnumerable enumerable) end = counter + enumerable.Count; } - public readonly TSource Current { get; } + public TSource Current { get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() @@ -117,7 +120,7 @@ internal DisposableEnumerator(in RepeatEnumerable enumerable) end = counter + enumerable.Count; } - public readonly TSource Current { get; } + public TSource Current { get; } readonly TSource IEnumerator.Current => Current; readonly object? IEnumerator.Current @@ -129,6 +132,7 @@ public bool MoveNext() => ++counter <= end; [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); @@ -162,10 +166,6 @@ public bool Contains(TSource value, IEqualityComparer? comparer) _ => count is not 0 && comparer.Equals(this.value, value) }; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RepeatEnumerable Select(Func selector) - => Select>(new FunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public RepeatEnumerable Select(TSelector selector = default) where TSelector : struct, IFunction @@ -173,15 +173,14 @@ public RepeatEnumerable Select(Func selector public TSource[] ToArray() { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var array = new TSource[Count]; + var array = Utils.AllocateUninitializedArray(Count); CopyTo(array.AsSpan()); return array; } - public IMemoryOwner ToArray(MemoryPool pool) + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) { - var result = pool.RentSliced(Count); + var result = pool.Lease(Count, clearOnDispose); CopyTo(result.Memory.Span); return result; } @@ -213,7 +212,7 @@ public static void CopyToVector(this RepeatEnumerable source, for (var index = 0; index < destinationVectors.Length; index++) destinationVectors[index] = vector; - for (var index = count - (count % Vector.Count); index < count && index < destination.Length; index++) + for (var index = count - (count % Vector.Count); index < count; index++) destination[index] = value; } else @@ -227,15 +226,15 @@ public static TSource[] ToArrayVector(this RepeatEnumerable so where TSource : struct { // ReSharper disable once HeapView.ObjectAllocation.Evident - var array = new TSource[source.count]; + var array = Utils.AllocateUninitializedArray(source.count); source.CopyToVector(array.AsSpan()); return array; } - public static IMemoryOwner ToArrayVector(this RepeatEnumerable source, MemoryPool pool) + public static Lease ToArrayVector(this RepeatEnumerable source, ArrayPool pool, bool clearOnDispose = default) where TSource : struct { - var result = pool.RentSliced(source.count); + var result = pool.Lease(source.count, clearOnDispose); source.CopyToVector(result.Memory.Span); return result; } diff --git a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Return.cs b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Return.cs similarity index 80% rename from NetFabric.Hyperlinq/Generation/ValueEnumerable/Return.cs rename to NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Return.cs index 6ecd443e8..2011435bd 100644 --- a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Return.cs +++ b/NetFabric.Hyperlinq.Core/Generation/ValueEnumerable/Return.cs @@ -23,22 +23,20 @@ public static partial class ValueEnumerable internal ReturnEnumerable(TSource value) => this.value = value; - public readonly int Count + public int Count => 1; - public readonly TSource this[int index] + public TSource this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get + get => index switch { - if (index is not 0) Throw.IndexOutOfRangeException(); - - return value; - } + 0 => value, + _ => Throw.ArgumentOutOfRangeException(nameof(index)) + }; } - TSource IReadOnlyList.this[int index] - => this[index]; + TSource IList.this[int index] { get => this[index]; @@ -49,14 +47,17 @@ internal ReturnEnumerable(TSource value) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new Enumerator(in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + DisposableEnumerator IValueEnumerable.GetEnumerator() + => new(in this); + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(in this); @@ -74,7 +75,7 @@ public void CopyTo(Span span) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyTo(TSource[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); + => CopyTo(array.AsSpan(arrayIndex)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Contains(TSource item) @@ -114,7 +115,7 @@ internal Enumerator(in ReturnEnumerable enumerable) => (Current, moveNext) = (enumerable.value, true); - public readonly TSource Current { get; } + public TSource Current { get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() @@ -138,7 +139,7 @@ internal DisposableEnumerator(in ReturnEnumerable enumerable) } - public readonly TSource Current { get; } + public TSource Current { get; } readonly TSource IEnumerator.Current => Current; readonly object? IEnumerator.Current @@ -172,10 +173,6 @@ public bool Contains(TSource value, IEqualityComparer? comparer) _ => comparer.Equals(this.value, value) }; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReturnEnumerable Select(Func selector) - => Select>(new FunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReturnEnumerable Select(TSelector selector = default) where TSelector : struct, IFunction @@ -206,11 +203,6 @@ public TSource[] ToArray() public List ToList() => new(1) { value }; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) where TKey : notnull @@ -218,11 +210,6 @@ public List ToList() // ReSharper disable once HeapView.ObjectAllocation.Evident => new(new Dictionary(1, comparer) { { keySelector.Invoke(value), value } }); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) where TKey : notnull diff --git a/NetFabric.Hyperlinq/GlobalSuppressions.cs b/NetFabric.Hyperlinq.Core/GlobalSuppressions.cs similarity index 100% rename from NetFabric.Hyperlinq/GlobalSuppressions.cs rename to NetFabric.Hyperlinq.Core/GlobalSuppressions.cs diff --git a/NetFabric.Hyperlinq.Core/Lease.cs b/NetFabric.Hyperlinq.Core/Lease.cs new file mode 100644 index 000000000..b9eb58550 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Lease.cs @@ -0,0 +1,224 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static class Lease + { + static class EmptyLease + { + // ReSharper disable once InconsistentNaming + internal static readonly Lease Value = new(ArrayPool.Shared, 0, default); + } + + public static Lease Empty() + => EmptyLease.Value; + } + + public sealed class Lease + : IMemoryOwner + , IValueEnumerable.DisposableEnumerator> + { + readonly ArrayPool pool; + readonly bool clearOnDispose; + T[]? rented; + int length; + + internal Lease(ArrayPool pool, int length, bool clearOnDispose) + { + Debug.Assert(length >= 0); + + this.pool = pool; + this.length = length; + this.clearOnDispose = clearOnDispose; + rented = length is 0 + ? Array.Empty() + : pool.Rent(length); + } + + /// + /// Gets or sets the length of memory to be used. + /// + public int Length + { + get => length; + set + { + var array = rented; + if (array is null) + Throw.ObjectDisposedException(nameof(Lease)); + if (value < 0 || value > array.Length) + Throw.ArgumentOutOfRangeException(nameof(value)); + + length = value; + } + } + + /// + /// Gets all the memory rented. + /// + public T[] Rented + { + get + { + var array = rented; + if (array is null) + Throw.ObjectDisposedException(nameof(Lease)); + return array; + } + } + + /// + /// Gets the slice of memory to be used. + /// + public Memory Memory + { + get + { + var array = rented; + if (array is null) + Throw.ObjectDisposedException(nameof(Lease)); + return array.AsMemory(0, length); + } + } + + /// + /// Gets the slice of memory that is rented but not used. + /// + public Memory Remaining + { + get + { + var array = rented; + if (array is null) + Throw.ObjectDisposedException(nameof(Lease)); + return array.AsMemory(length); + } + } + + public void Dispose() + { + if (length is 0) + return; // do not dispose empty + + var array = rented; + if (array is null) + return; // it's already disposed + + rented = null; + pool.Return(array, clearOnDispose); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + { + var array = rented; + if (array is null) + Throw.ObjectDisposedException(nameof(Lease)); + return new Enumerator(array, length); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + DisposableEnumerator IValueEnumerable.GetEnumerator() + => GetDisposableEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetDisposableEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetDisposableEnumerator(); + + DisposableEnumerator GetDisposableEnumerator() + { + var array = rented; + if (array is null) + Throw.ObjectDisposedException(nameof(Lease)); + return new DisposableEnumerator(array, length); + } + + public struct Enumerator + { + readonly T[] source; + readonly int length; + int index; + + internal Enumerator(T[] source, int length) + { + this.source = source; + this.length = length; + index = -1; + } + + public readonly T Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + if (index >= length) + return false; + index++; + return index < length; + } + } + + public struct DisposableEnumerator + : IEnumerator + { + readonly T[] source; + readonly int length; + int index; + + internal DisposableEnumerator(T[] source, int length) + { + this.source = source; + this.length = length; + index = -1; + } + + public readonly T Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => source[index]; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + if (index >= length) + return false; + index++; + return index < length; + } + + public void Reset() + => index = -1; + + public readonly void Dispose() + { } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ArrayExtensions.ArraySegmentValueEnumerable AsValueEnumerable() + => rented is null + ? Throw.ObjectDisposedException>(nameof(Lease)) + : new ArraySegment(rented, 0, length).AsValueEnumerable(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease AsEnumerable() + => this; + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/NetFabric.Hyperlinq.Core.csproj b/NetFabric.Hyperlinq.Core/NetFabric.Hyperlinq.Core.csproj new file mode 100644 index 000000000..c36b41a0c --- /dev/null +++ b/NetFabric.Hyperlinq.Core/NetFabric.Hyperlinq.Core.csproj @@ -0,0 +1,84 @@ + + + + netstandard2.0;netcoreapp3.1;net5.0;net6.0 + NetFabric.Hyperlinq.Core + NetFabric.Hyperlinq.Core + The main assembly of NetFabric.Hyperlinq. + 1.0.0-beta00 + Icon.png + LICENSE + netfabric, hyperlinq, linq, enumeration, extensions, performance + true + true + true + snupkg + true + + NetFabric.Hyperlinq + + + + + $(NoWarn);8600;8601;8602;8603;8604 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + all + runtime; build; native; contentfiles; analyzers + + + all + runtime; build; native; contentfiles; analyzers + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + True + True + Resource.resx + + + + + + ResXFileCodeGenerator + Resource.Designer.cs + + + + diff --git a/NetFabric.Hyperlinq/Option/NoneOption.cs b/NetFabric.Hyperlinq.Core/Option/NoneOption.cs similarity index 83% rename from NetFabric.Hyperlinq/Option/NoneOption.cs rename to NetFabric.Hyperlinq.Core/Option/NoneOption.cs index 1e43ad1a9..8998dc5b8 100644 --- a/NetFabric.Hyperlinq/Option/NoneOption.cs +++ b/NetFabric.Hyperlinq.Core/Option/NoneOption.cs @@ -1,5 +1,3 @@ -using System; - namespace NetFabric.Hyperlinq { public readonly struct NoneOption diff --git a/NetFabric.Hyperlinq/Option/Option.cs b/NetFabric.Hyperlinq.Core/Option/Option.cs similarity index 72% rename from NetFabric.Hyperlinq/Option/Option.cs rename to NetFabric.Hyperlinq.Core/Option/Option.cs index 560475064..88744c90d 100644 --- a/NetFabric.Hyperlinq/Option/Option.cs +++ b/NetFabric.Hyperlinq.Core/Option/Option.cs @@ -40,7 +40,7 @@ public bool IsNone public TValue Value { get; } - public readonly void Deconstruct(out bool hasValue, out TValue value) + public void Deconstruct(out bool hasValue, out TValue value) { hasValue = IsSome; value = Value; @@ -53,7 +53,7 @@ public bool IsNone [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly TOut Match(Func some, Func none) + public TOut Match(Func some, Func none) => IsSome switch { true => some(Value), @@ -61,7 +61,7 @@ public bool IsNone }; - public readonly ValueTask MatchAsync(Func> some, Func> none, CancellationToken cancellationToken = default) + public ValueTask MatchAsync(Func> some, Func> none, CancellationToken cancellationToken = default) => IsSome switch { true => some(Value, cancellationToken), @@ -69,7 +69,7 @@ public bool IsNone }; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void Match(Action some, Action none) + public void Match(Action some, Action none) { if (IsSome) some(Value); @@ -78,7 +78,7 @@ public bool IsNone } - public readonly ValueTask MatchAsync(Func some, Func none, CancellationToken cancellationToken = default) + public ValueTask MatchAsync(Func some, Func none, CancellationToken cancellationToken = default) => IsSome switch { true => some(Value, cancellationToken), @@ -86,7 +86,7 @@ public bool IsNone }; - public readonly Option Bind(Func> bind) + public Option Bind(Func> bind) => IsSome switch { true => bind(Value), @@ -94,7 +94,7 @@ public bool IsNone }; - public readonly int Count() + public int Count() => IsSome switch { true => 1, @@ -103,20 +103,21 @@ public bool IsNone [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any() + public bool Any() => IsSome; - public readonly bool Contains(TValue value, IEqualityComparer? comparer = default) + public bool Contains(TValue value, IEqualityComparer? comparer = default) => IsSome - && (comparer?.Equals(Value, value) ?? EqualityComparer.Default.Equals(Value, value)); + && (comparer?.Equals(Value, value) + ?? EqualityComparer.Default.Equals(Value, value)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Option Where(Func predicate) + public Option Where(Func predicate) => Where(new FunctionWrapper(predicate)); - public readonly Option Where(TPredicate predicate = default) + public Option Where(TPredicate predicate = default) where TPredicate : struct, IFunction => IsSome && predicate.Invoke(Value) ? this @@ -124,15 +125,15 @@ public bool IsNone [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueTask> WhereAsync(Func> predicate, CancellationToken cancellationToken = default) + public ValueTask> WhereAsync(Func> predicate, CancellationToken cancellationToken = default) => WhereAsync(new AsyncFunctionWrapper(predicate), cancellationToken); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueTask> WhereAsync(CancellationToken cancellationToken = default) + public ValueTask> WhereAsync(CancellationToken cancellationToken = default) where TPredicate : struct, IAsyncFunction => WhereAsync(default, cancellationToken); - public async readonly ValueTask> WhereAsync(TPredicate predicate, CancellationToken cancellationToken = default) + public async ValueTask> WhereAsync(TPredicate predicate, CancellationToken cancellationToken = default) where TPredicate : struct, IAsyncFunction => IsSome && await predicate.InvokeAsync(Value, cancellationToken).ConfigureAwait(false) ? this @@ -140,10 +141,10 @@ public bool IsNone [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Option Select(Func selector) + public Option Select(Func selector) => Select>(new FunctionWrapper(selector)); - public readonly Option Select(TSelector selector = default) + public Option Select(TSelector selector = default) where TSelector : struct, IFunction => IsSome switch { @@ -153,15 +154,15 @@ public bool IsNone [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueTask> SelectAsync(Func> selector, CancellationToken cancellationToken = default) + public ValueTask> SelectAsync(Func> selector, CancellationToken cancellationToken = default) => SelectAsync>(new AsyncFunctionWrapper(selector), cancellationToken); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueTask> SelectAsync(CancellationToken cancellationToken = default) + public ValueTask> SelectAsync(CancellationToken cancellationToken = default) where TSelector : struct, IAsyncFunction => SelectAsync(default, cancellationToken); - public async readonly ValueTask> SelectAsync(TSelector selector, CancellationToken cancellationToken = default) + public async ValueTask> SelectAsync(TSelector selector, CancellationToken cancellationToken = default) where TSelector : struct, IAsyncFunction => IsSome switch { @@ -171,20 +172,20 @@ public bool IsNone [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SelectManyEnumerable> SelectMany(Func selector) + public SelectManyEnumerable> SelectMany(Func selector) where TSubEnumerable : IValueEnumerable where TSubEnumerator : struct, IEnumerator => SelectMany>(new FunctionWrapper(selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SelectManyEnumerable SelectMany(TSelector selector) + public SelectManyEnumerable SelectMany(TSelector selector) where TSubEnumerable : IValueEnumerable where TSubEnumerator : struct, IEnumerator where TSelector : struct, IFunction => new(in this, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Option ElementAt(int index) + public Option ElementAt(int index) => index switch { 0 => this, @@ -193,25 +194,25 @@ public bool IsNone [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Option First() + public Option First() => this; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Option Single() + public Option Single() => this; - public readonly TValue[] ToArray() + public TValue[] ToArray() => IsSome switch { // ReSharper disable once HeapView.ObjectAllocation.Evident - true => new TValue[] { Value }, + true => new[] { Value }, _ => Array.Empty() }; - public readonly List ToList() + public List ToList() => IsSome switch { // ReSharper disable once HeapView.ObjectAllocation.Evident @@ -221,7 +222,6 @@ public bool IsNone }; - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public readonly partial struct SelectManyEnumerable : IValueEnumerable.Enumerator> @@ -236,12 +236,14 @@ internal SelectManyEnumerable(in Option source, TSelector selector) => (this.source, this.selector) = (source, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -249,10 +251,11 @@ internal SelectManyEnumerable(in Option source, TSelector selector) public struct Enumerator : IEnumerator { - readonly Option source; + readonly Option source; +#pragma warning disable IDE0044 // Add readonly modifier TSelector selector; - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TSubEnumerator subEnumerator; // do not make readonly + TSubEnumerator subEnumerator; +#pragma warning restore IDE0044 // Add readonly modifier int state; internal Enumerator(in SelectManyEnumerable enumerable) @@ -265,8 +268,6 @@ internal Enumerator(in SelectManyEnumerable.Current - => Current; readonly object? IEnumerator.Current // ReSharper disable once HeapView.PossibleBoxingAllocation => Current; @@ -302,6 +303,7 @@ public bool MoveNext() } [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); diff --git a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.AsyncValueEnumerable.cs similarity index 88% rename from NetFabric.Hyperlinq/Partitioning/Skip/Skip.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.AsyncValueEnumerable.cs index ba45e761b..35fa68594 100644 --- a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.AsyncValueEnumerable.cs @@ -24,18 +24,15 @@ public static partial class AsyncValueEnumerableExtensions where TEnumerator : struct, IAsyncEnumerator { readonly TEnumerable source; - readonly int count; + readonly int offset; - internal SkipEnumerable(in TEnumerable source, int count) - { - this.source = source; - this.count = count; - } + internal SkipEnumerable(in TEnumerable source, int offset) + => (this.source, this.offset) = (source, offset); - - public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) => new Enumerator(in this, cancellationToken); [StructLayout(LayoutKind.Auto)] @@ -43,20 +40,23 @@ public struct Enumerator : IAsyncEnumerator , IAsyncStateMachine { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; +#pragma warning restore IDE0044 // Add readonly modifier int counter; int state; AsyncValueTaskMethodBuilder builder; +#pragma warning disable IDE1006 // Naming Styles bool s__1; bool s__2; +#pragma warning restore IDE1006 // Naming Styles ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; internal Enumerator(in SkipEnumerable enumerable, CancellationToken cancellationToken) { enumerator = enumerable.source.GetAsyncEnumerator(cancellationToken); - counter = enumerable.count; + counter = enumerable.offset; state = default; builder = default; @@ -91,7 +91,7 @@ public ValueTask MoveNextAsync() return builder.Task; } - public readonly ValueTask DisposeAsync() + public ValueTask DisposeAsync() => enumerator.DisposeAsync(); void IAsyncStateMachine.MoveNext() @@ -170,11 +170,11 @@ void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipEnumerable Skip(int count) - => source.Skip(this.count + count); + => new(source, offset + count); [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipTakeEnumerable Take(int count) - => source.SkipTake(this.count, count); + => new(source, offset, count); } } } diff --git a/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ReadOnlyList.cs new file mode 100644 index 000000000..132bfd81a --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ReadOnlyList.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ReadOnlyListExtensions + { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static SkipTakeEnumerable Skip(this TList source, int count) + where TList : struct, IReadOnlyList + => new(in source, Utils.Skip(source.Count, count)); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ValueEnumerable.cs similarity index 77% rename from NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ValueEnumerable.cs index 356d662c3..e26b528b6 100644 --- a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ValueEnumerable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -23,34 +22,33 @@ public static partial class ValueEnumerableExtensions where TEnumerator : struct, IEnumerator { readonly TEnumerable source; - readonly int count; - - internal SkipEnumerable(in TEnumerable source, int count) - { - this.source = source; - this.count = count; - } + readonly int offset; + internal SkipEnumerable(in TEnumerable source, int offset) + => (this.source, this.offset) = (source, offset); - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(in this); [StructLayout(LayoutKind.Auto)] public struct Enumerator : IEnumerator { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; +#pragma warning restore IDE0044 // Add readonly modifier int counter; internal Enumerator(in SkipEnumerable enumerable) { enumerator = enumerable.source.GetEnumerator(); - counter = enumerable.count; + counter = enumerable.offset; } public readonly TSource Current @@ -62,7 +60,7 @@ internal Enumerator(in SkipEnumerable enumera => enumerator.Current; readonly object? IEnumerator.Current // ReSharper disable once HeapView.PossibleBoxingAllocation - => enumerator.Current!; + => enumerator.Current; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() @@ -79,20 +77,21 @@ public bool MoveNext() } [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); - public readonly void Dispose() + public void Dispose() => enumerator.Dispose(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipEnumerable Skip(int count) - => source.Skip(this.count + count); + => new(source, offset + count); [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipTakeEnumerable Take(int count) - => source.SkipTake(this.count, count); + => new(source, offset, count); } } } diff --git a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ValueReadOnlyCollection.cs similarity index 85% rename from NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ValueReadOnlyCollection.cs index b6743771e..b17460437 100644 --- a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ValueReadOnlyCollection.cs @@ -10,6 +10,6 @@ public static partial class ValueReadOnlyCollectionExtensions public static SkipTakeEnumerable Skip(this TEnumerable source, int count) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator - => source.SkipTake(count, source.Count); + => new(in source, Utils.Skip(source.Count, count)); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ValueReadOnlyList.cs new file mode 100644 index 000000000..6c808b833 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Partitioning/Skip/Skip.ValueReadOnlyList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueReadOnlyCollectionExtensions.SkipTakeEnumerable Skip(this TEnumerable source, int count) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.Skip(source, count); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs similarity index 86% rename from NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs index e92456e42..02933aa2b 100644 --- a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs @@ -11,12 +11,6 @@ namespace NetFabric.Hyperlinq public static partial class AsyncValueEnumerableExtensions { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static SkipTakeEnumerable SkipTake(this TEnumerable source, int skipCount, int takeCount) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - => new(in source, skipCount, takeCount); - [StructLayout(LayoutKind.Auto)] public readonly partial struct SkipTakeEnumerable : IAsyncValueEnumerable.Enumerator> @@ -24,21 +18,20 @@ public static partial class AsyncValueEnumerableExtensions where TEnumerator : struct, IAsyncEnumerator { readonly TEnumerable source; - readonly int skipCount; - readonly int takeCount; + readonly int offset; + readonly int count; - internal SkipTakeEnumerable(in TEnumerable source, int skipCount, int takeCount) - { - this.source = source; - this.skipCount = skipCount; - this.takeCount = takeCount; - } + internal SkipTakeEnumerable(in TEnumerable source, int offset, int count) + => (this.source, this.offset, this.count) = (source, offset, count); + internal SkipTakeEnumerable(in TEnumerable source, (int Offset, int Count) slice) + => (this.source, offset, count) = (source, slice.Offset, slice.Count); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) => new Enumerator(in this, cancellationToken); [StructLayout(LayoutKind.Auto)] @@ -46,23 +39,26 @@ public struct Enumerator : IAsyncEnumerator , IAsyncStateMachine { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; +#pragma warning restore IDE0044 // Add readonly modifier int skipCounter; int takeCounter; int state; AsyncValueTaskMethodBuilder builder; +#pragma warning disable IDE1006 // Naming Styles bool s__1; bool s__2; +#pragma warning restore IDE1006 // Naming Styles ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__2; internal Enumerator(in SkipTakeEnumerable enumerable, CancellationToken cancellationToken) { enumerator = enumerable.source.GetAsyncEnumerator(cancellationToken); - skipCounter = enumerable.skipCount; - takeCounter = enumerable.takeCount; + skipCounter = enumerable.offset; + takeCounter = enumerable.count; state = default; builder = default; @@ -213,12 +209,21 @@ void IAsyncStateMachine.MoveNext() } void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) - { } + { + } } + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable Skip(int count) + => new(source, Utils.Skip(this.count, offset + count)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipTakeEnumerable Take(int count) - => source.SkipTake(skipCount, Math.Min(takeCount, count)); + => new(source, offset, Utils.Take(this.count, count)); + + #endregion } } } diff --git a/NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.ReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.ReadOnlyList.cs new file mode 100644 index 000000000..69727b49b --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.ReadOnlyList.cs @@ -0,0 +1,282 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ReadOnlyListExtensions + { + [StructLayout(LayoutKind.Auto)] + public readonly partial struct SkipTakeEnumerable + : IValueReadOnlyList.DisposableEnumerator> + , IList + where TList : struct, IReadOnlyList + { + readonly TList source; + readonly int offset; + + internal SkipTakeEnumerable(in TList source, int offset, int count) + => (this.source, this.offset, Count) = (source, offset, count); + + internal SkipTakeEnumerable(in TList source, (int Offset, int Count) slice) + => (this.source, offset, Count) = (source, slice.Offset, slice.Count); + + public int Count { get; } + + public TSource this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + ThrowIfArgument.OutOfRange(index, Count, nameof(index)); + return source[index + offset]; + } + } + + TSource IList.this[int index] + { + get => this[index]; + + [ExcludeFromCodeCoverage] + // ReSharper disable once ValueParameterNotUsed + set => Throw.NotSupportedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + => new(in this); + + DisposableEnumerator IValueEnumerable.GetEnumerator() + => new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new DisposableEnumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new DisposableEnumerator(in this); + + bool ICollection.IsReadOnly + => true; + + public void CopyTo(Span span) + { + if (Count is 0) + return; + + if (span.Length < Count) + Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); + + if (offset is 0) + { + for(var index = 0; index < Count; index++) + span[index] = source[index]; + } + else + { + for(var index = 0; index < Count; index++) + span[index] = source[index + offset]; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(TSource[] array, int arrayIndex) + { + if (Count is 0) + return; + + // ReSharper disable once HeapView.PossibleBoxingAllocation + if (offset is 0 && Count == source.Count && source is ICollection collection) + collection.CopyTo(array, arrayIndex); + else + CopyTo(array.AsSpan(arrayIndex)); + } + + public bool Contains(TSource item) + => Contains(item, EqualityComparer.Default); + + public int IndexOf(TSource item) + { + if (source.Count is 0) + return -1; + + // ReSharper disable once HeapView.PossibleBoxingAllocation + if (offset is 0 && Count == source.Count && source is IList list) + return list.IndexOf(item); + + return ValueReadOnlyCollectionExtensions.IndexOf, DisposableEnumerator, TSource>(this, item); + } + + [ExcludeFromCodeCoverage] + void ICollection.Add(TSource item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + void ICollection.Clear() + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + bool ICollection.Remove(TSource item) + => Throw.NotSupportedException(); + + [ExcludeFromCodeCoverage] + void IList.Insert(int index, TSource item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + void IList.RemoveAt(int index) + => Throw.NotSupportedException(); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + { + readonly TList source; + readonly int end; + int index; + + internal Enumerator(in SkipTakeEnumerable enumerable) + { + source = enumerable.source; + index = enumerable.offset - 1; + end = index + enumerable.Count; + } + + public readonly TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + + public bool MoveNext() + => ++index <= end; + } + + [StructLayout(LayoutKind.Auto)] + public struct DisposableEnumerator + : IEnumerator + { + readonly TList source; + readonly int end; + int index; + + internal DisposableEnumerator(in SkipTakeEnumerable enumerable) + { + source = enumerable.source; + index = enumerable.offset - 1; + end = index + enumerable.Count; + } + + public readonly TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source[index]; + } + readonly TSource IEnumerator.Current + => source[index]; + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => source[index]; + + public bool MoveNext() + => ++index <= end; + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public readonly void Dispose() + { } + } + + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable Skip(int count) + { + var (newOffset, newCount) = Utils.Skip(Count, count); + return new SkipTakeEnumerable(source, offset + newOffset, newCount); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable Take(int count) + => new(source, offset, Utils.Take(Count, count)); + + #endregion + + #region Conversion + + public SkipTakeEnumerable AsValueEnumerable() + => this; + + public SkipTakeEnumerable AsEnumerable() + => this; + + #endregion + + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueReadOnlyListExtensions.SelectEnumerable, DisposableEnumerator, TSource, TResult, FunctionWrapper> Select(Func selector) + => ValueReadOnlyListExtensions.Select, DisposableEnumerator, TSource, TResult>(this, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueReadOnlyListExtensions.SelectEnumerable, DisposableEnumerator, TSource, TResult, TSelector> Select(TSelector selector = default) + where TSelector : struct, IFunction + => ValueReadOnlyListExtensions.Select, DisposableEnumerator, TSource, TResult, TSelector>(this, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueReadOnlyListExtensions.SelectAtEnumerable, DisposableEnumerator, TSource, TResult, FunctionWrapper> Select(Func selector) + => ValueReadOnlyListExtensions.Select, DisposableEnumerator, TSource, TResult>(this, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueReadOnlyListExtensions.SelectAtEnumerable, DisposableEnumerator, TSource, TResult, TSelector> SelectAt(TSelector selector = default) + where TSelector : struct, IFunction + => ValueReadOnlyListExtensions.SelectAt, DisposableEnumerator, TSource, TResult, TSelector>(this, selector); + + #endregion + + public bool Contains(TSource value, IEqualityComparer? comparer) + { + if (source.Count is 0) + return false; + + if (comparer.UseDefaultComparer()) + { + // ReSharper disable once HeapView.PossibleBoxingAllocation + // ReSharper disable once HeapView.BoxingAllocation + if (offset is 0 && Count == source.Count && source is ICollection collection) + return collection.Contains(value); + + return DefaultContains(source, value, offset, Count); + } + + return ComparerContains(source, value, comparer, offset, Count); + + static bool DefaultContains(TList source, TSource value, int offset, int count) + { + var end = offset + count; + for(var index = offset; index < end; index++) + { + if (EqualityComparer.Default.Equals(source[index], value!)) + return true; + } + return false; + } + + static bool ComparerContains(TList source, TSource value, IEqualityComparer? comparer, int offset, int count) + { + comparer ??= EqualityComparer.Default; + var end = offset + count; + for(var index = offset; index < end; index++) + { + if (comparer.Equals(source[index], value!)) + return true; + } + return false; + } + } + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs similarity index 70% rename from NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs index 251b0cacd..e3c11e3bb 100644 --- a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs @@ -9,12 +9,6 @@ namespace NetFabric.Hyperlinq { public static partial class ValueEnumerableExtensions { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static SkipTakeEnumerable SkipTake(this TEnumerable source, int skipCount, int takeCount) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => new(in source, skipCount, takeCount); [StructLayout(LayoutKind.Auto)] public readonly partial struct SkipTakeEnumerable @@ -23,39 +17,40 @@ public static partial class ValueEnumerableExtensions where TEnumerator : struct, IEnumerator { readonly TEnumerable source; - readonly int skipCount; - readonly int takeCount; + readonly int offset; + readonly int count; - internal SkipTakeEnumerable(in TEnumerable source, int skipCount, int takeCount) - { - this.source = source; - this.skipCount = skipCount; - this.takeCount = takeCount; - } + internal SkipTakeEnumerable(in TEnumerable source, int offset, int count) + => (this.source, this.offset, this.count) = (source, offset, count); + internal SkipTakeEnumerable(in TEnumerable source, (int Offset, int Count) slice) + => (this.source, offset, count) = (source, slice.Offset, slice.Count); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(in this); [StructLayout(LayoutKind.Auto)] public struct Enumerator : IEnumerator { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; +#pragma warning restore IDE0044 // Add readonly modifier int skipCounter; int takeCounter; internal Enumerator(in SkipTakeEnumerable enumerable) { enumerator = enumerable.source.GetEnumerator(); - skipCounter = enumerable.skipCount; - takeCounter = enumerable.takeCount; + skipCounter = enumerable.offset; + takeCounter = enumerable.count; } public readonly TSource Current @@ -93,6 +88,7 @@ public bool MoveNext() } [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); @@ -100,9 +96,17 @@ public void Dispose() => enumerator.Dispose(); } + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable Skip(int count) + => new(source, Utils.Skip(this.count, offset + count)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipTakeEnumerable Take(int count) - => source.SkipTake(skipCount, Math.Min(takeCount, count)); + => new(source, offset, Utils.Take(this.count, count)); + + #endregion } } } diff --git a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs similarity index 65% rename from NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs index cf375d7a4..d3070fa55 100644 --- a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs @@ -9,12 +9,6 @@ namespace NetFabric.Hyperlinq { public static partial class ValueReadOnlyCollectionExtensions { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static SkipTakeEnumerable SkipTake(this TEnumerable source, int skipCount, int takeCount) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => new(in source, skipCount, takeCount); [StructLayout(LayoutKind.Auto)] public readonly partial struct SkipTakeEnumerable @@ -24,23 +18,24 @@ public static partial class ValueReadOnlyCollectionExtensions where TEnumerator : struct, IEnumerator { readonly TEnumerable source; - readonly int skipCount; + readonly int offset; - internal SkipTakeEnumerable(in TEnumerable source, int skipCount, int takeCount) - { - this.source = source; - (this.skipCount, Count) = Utils.SkipTake(source.Count, skipCount, takeCount); - } + internal SkipTakeEnumerable(in TEnumerable source, int offset, int count) + => (this.source, this.offset, Count) = (source, offset, count); - public readonly int Count { get; } + internal SkipTakeEnumerable(in TEnumerable source, (int Offset, int Count) slice) + => (this.source, offset, Count) = (source, slice.Offset, slice.Count); + + public int Count { get; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(in this); bool ICollection.IsReadOnly @@ -48,16 +43,16 @@ internal SkipTakeEnumerable(in TEnumerable source, int skipCount, int takeCount) public void CopyTo(Span span) { - if (span.Length < Count) - Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - if (Count is 0) return; + if (span.Length < Count) + Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); + using var enumerator = source.GetEnumerator(); // skip - for (var counter = 0; counter < skipCount; counter++) + for (var counter = 0; counter < offset; counter++) { if (!enumerator.MoveNext()) Throw.InvalidOperationException(); @@ -75,51 +70,19 @@ public void CopyTo(Span span) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyTo(TSource[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - public bool Contains(TSource item) { if (Count is 0) - return false; - - if (skipCount is 0 && Count == source.Count && source is ICollection collection) - return collection.Contains(item); - - using var enumerator = source.GetEnumerator(); - - // skip - for (var counter = 0; counter < skipCount; counter++) - { - if (!enumerator.MoveNext()) - Throw.InvalidOperationException(); - } - - // take - if (Utils.IsValueType()) - { - for (var counter = 0; counter < Count; counter++) - { - if (!enumerator.MoveNext()) - Throw.InvalidOperationException(); + return; - if (EqualityComparer.Default.Equals(enumerator.Current, item)) - return true; - } - } + // ReSharper disable once HeapView.PossibleBoxingAllocation + if (offset is 0 && Count == source.Count && source is ICollection collection) + collection.CopyTo(array, arrayIndex); else - { - var defaultComparer = EqualityComparer.Default; - for (var counter = 0; counter < Count; counter++) - { - if (!enumerator.MoveNext()) - Throw.InvalidOperationException(); - - if (defaultComparer.Equals(enumerator.Current, item)) - return true; - } - } - return false; + CopyTo(array.AsSpan(arrayIndex)); } + + public bool Contains(TSource item) + => Contains(item, EqualityComparer.Default); [ExcludeFromCodeCoverage] void ICollection.Add(TSource item) @@ -135,8 +98,9 @@ bool ICollection.Remove(TSource item) public struct Enumerator : IEnumerator { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; +#pragma warning restore IDE0044 // Add readonly modifier int skipCounter; int takeCounter; EnumeratorState state; @@ -144,7 +108,7 @@ public struct Enumerator internal Enumerator(in SkipTakeEnumerable enumerable) { enumerator = enumerable.source.GetEnumerator(); - skipCounter = enumerable.skipCount; + skipCounter = enumerable.offset; takeCounter = enumerable.Count; state = takeCounter > 0 ? EnumeratorState.Uninitialized : EnumeratorState.Complete; } @@ -199,6 +163,7 @@ public bool MoveNext() } [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); @@ -211,31 +176,30 @@ public bool Contains(TSource value, IEqualityComparer? comparer) if (source.Count is 0) return false; - if (comparer is null || ReferenceEquals(comparer, EqualityComparer.Default)) + if (comparer.UseDefaultComparer()) { - if (skipCount is 0 && Count == source.Count && source is ICollection collection) + // ReSharper disable once HeapView.PossibleBoxingAllocation + if (offset is 0 && Count == source.Count && source is ICollection collection) return collection.Contains(value); - if (Utils.IsValueType()) - return DefaultContains(source, value, skipCount, Count); + return DefaultContains(source, value, offset, Count); } - comparer ??= EqualityComparer.Default; - return ComparerContains(source, value, comparer, skipCount, Count); + return ComparerContains(source, value, comparer, offset, Count); - static bool DefaultContains(TEnumerable source, TSource value, int skipCount, int takeCount) + static bool DefaultContains(TEnumerable source, TSource value, int offset, int count) { using var enumerator = source.GetEnumerator(); // skip - for (var counter = 0; counter < skipCount; counter++) + for (var counter = 0; counter < offset; counter++) { if (!enumerator.MoveNext()) Throw.InvalidOperationException(); } // take - for (var counter = 0; counter < takeCount; counter++) + for (var counter = 0; counter < count; counter++) { if (!enumerator.MoveNext()) Throw.InvalidOperationException(); @@ -246,19 +210,20 @@ static bool DefaultContains(TEnumerable source, TSource value, int skipCount, in return false; } - static bool ComparerContains(TEnumerable source, TSource value, IEqualityComparer comparer, int skipCount, int takeCount) + static bool ComparerContains(TEnumerable source, TSource value, IEqualityComparer? comparer, int offset, int count) { + comparer ??= EqualityComparer.Default; using var enumerator = source.GetEnumerator(); // skip - for (var counter = 0; counter < skipCount; counter++) + for (var counter = 0; counter < offset; counter++) { if (!enumerator.MoveNext()) Throw.InvalidOperationException(); } // take - for (var counter = 0; counter < takeCount; counter++) + for (var counter = 0; counter < count; counter++) { if (!enumerator.MoveNext()) Throw.InvalidOperationException(); @@ -270,15 +235,20 @@ static bool ComparerContains(TEnumerable source, TSource value, IEqualityCompare } } + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable Skip(int count) + { + var (newOffset, newCount) = Utils.Skip(Count, count); + return new SkipTakeEnumerable(source, offset + newOffset, newCount); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipTakeEnumerable Take(int count) - => source.SkipTake(skipCount, Math.Min(Count, count)); + => new(source, offset, Utils.Take(Count, count)); + + #endregion } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this in SkipTakeEnumerable source) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => source.Count; } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Partitioning/Take/Take.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.AsyncValueEnumerable.cs similarity index 91% rename from NetFabric.Hyperlinq/Partitioning/Take/Take.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Partitioning/Take/Take.AsyncValueEnumerable.cs index b780840f0..fe686d543 100644 --- a/NetFabric.Hyperlinq/Partitioning/Take/Take.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.AsyncValueEnumerable.cs @@ -29,11 +29,11 @@ public static partial class AsyncValueEnumerableExtensions internal TakeEnumerable(in TEnumerable source, int count) => (this.source, this.count) = (source, count); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) => new Enumerator(in this, cancellationToken); [StructLayout(LayoutKind.Auto)] @@ -41,13 +41,16 @@ public struct Enumerator : IAsyncEnumerator , IAsyncStateMachine { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; +#pragma warning restore IDE0044 // Add readonly modifier int counter; int state; AsyncValueTaskMethodBuilder builder; +#pragma warning disable IDE1006 // Naming Styles bool s__1; +#pragma warning restore IDE1006 // Naming Styles ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; ValueTaskAwaiter u__2; @@ -92,7 +95,7 @@ public ValueTask MoveNextAsync() return builder.Task; } - public readonly ValueTask DisposeAsync() + public ValueTask DisposeAsync() => enumerator.DisposeAsync(); void IAsyncStateMachine.MoveNext() @@ -173,7 +176,7 @@ void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) [MethodImpl(MethodImplOptions.AggressiveInlining)] public TakeEnumerable Take(int count) - => source.Take(Math.Min(this.count, count)); + => new(source, Utils.Take(this.count, count)); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ReadOnlyList.cs new file mode 100644 index 000000000..915fe8bcf --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ReadOnlyList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ReadOnlyListExtensions + { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static SkipTakeEnumerable Take(this TList source, int count) + where TList : struct, IReadOnlyList + => new(in source, 0, Utils.Take(source.Count, count)); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Partitioning/Take/Take.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ValueEnumerable.cs similarity index 85% rename from NetFabric.Hyperlinq/Partitioning/Take/Take.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ValueEnumerable.cs index 4be64afde..561203a42 100644 --- a/NetFabric.Hyperlinq/Partitioning/Take/Take.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ValueEnumerable.cs @@ -26,26 +26,25 @@ public static partial class ValueEnumerableExtensions readonly int count; internal TakeEnumerable(in TEnumerable source, int count) - { - this.source = source; - this.count = count; - } - + => (this.source, this.count) = (source, count); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(in this); [StructLayout(LayoutKind.Auto)] public struct Enumerator : IEnumerator { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; +#pragma warning restore IDE0044 // Add readonly modifier int counter; internal Enumerator(in TakeEnumerable enumerable) @@ -82,6 +81,7 @@ public bool MoveNext() } [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); @@ -91,7 +91,7 @@ public void Dispose() [MethodImpl(MethodImplOptions.AggressiveInlining)] public TakeEnumerable Take(int count) - => source.Take(Math.Min(this.count, count)); + => new(source, Utils.Take(this.count, count)); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Partitioning/Take/Take.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ValueReadOnlyCollection.cs similarity index 87% rename from NetFabric.Hyperlinq/Partitioning/Take/Take.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ValueReadOnlyCollection.cs index 510fad85e..489fbad86 100644 --- a/NetFabric.Hyperlinq/Partitioning/Take/Take.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ValueReadOnlyCollection.cs @@ -10,6 +10,6 @@ public static partial class ValueReadOnlyCollectionExtensions public static SkipTakeEnumerable Take(this TEnumerable source, int count) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator - => source.SkipTake(0, count); + => new(in source, 0, Utils.Take(source.Count, count)); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ValueReadOnlyList.cs new file mode 100644 index 000000000..02fa9d9ad --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Partitioning/Take/Take.ValueReadOnlyList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueReadOnlyCollectionExtensions.SkipTakeEnumerable Take(this TEnumerable source, int count) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.Take(source, count); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Projection/Select/Select.ArraySegment.cs b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ArraySegment.cs similarity index 66% rename from NetFabric.Hyperlinq/Projection/Select/Select.ArraySegment.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ArraySegment.cs index b5cecb90d..a8a19b00d 100644 --- a/NetFabric.Hyperlinq/Projection/Select/Select.ArraySegment.cs +++ b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ArraySegment.cs @@ -10,17 +10,15 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectEnumerable> Select(this in ArraySegment source, Func selector) + static ArraySegmentSelectEnumerable> Select(this in ArraySegment source, Func selector) => source.Select>(new FunctionWrapper(selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectEnumerable Select(this in ArraySegment source, TSelector selector = default) + static ArraySegmentSelectEnumerable Select(this in ArraySegment source, TSelector selector = default) where TSelector : struct, IFunction => new(in source, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public partial struct ArraySegmentSelectEnumerable : IValueReadOnlyList.Enumerator> @@ -34,15 +32,17 @@ internal ArraySegmentSelectEnumerable(in ArraySegment source, TSelector => (this.source, this.selector) = (source, selector); public readonly int Count - => source.Count; + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source.Count; + } public TResult this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if (index < 0 || index >= source.Count) Throw.IndexOutOfRangeException(); - + ThrowIfArgument.OutOfRange(index, Count, nameof(index)); return selector.Invoke(source.Array![index + source.Offset]); } } @@ -73,6 +73,9 @@ internal ArraySegmentSelectEnumerable(in ArraySegment source, TSelector public void CopyTo(Span span) { + if (Count is 0) + return; + if (span.Length < Count) Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); @@ -80,14 +83,14 @@ public void CopyTo(Span span) } void ICollection.CopyTo(TResult[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); + => CopyTo(array.AsSpan(arrayIndex)); void ICollection.Add(TResult item) => Throw.NotSupportedException(); void ICollection.Clear() => Throw.NotSupportedException(); public bool Contains(TResult item) - => ((ReadOnlySpan)source.AsSpan()).Contains(item, default, selector); + => source.AsReadOnlySpan().Contains(item, default, selector); bool ICollection.Remove(TResult item) => Throw.NotSupportedException(); @@ -103,7 +106,9 @@ public struct Enumerator : IEnumerator { readonly TSource[]? source; +#pragma warning disable IDE0044 // Add readonly modifier TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier readonly int end; int index; @@ -115,26 +120,32 @@ internal Enumerator(in ArraySegmentSelectEnumerable end = index + enumerable.source.Count; } - public readonly TResult Current + public TResult Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => selector.Invoke(source![index]); } - readonly TResult IEnumerator.Current - => selector.Invoke(source![index]); - readonly object? IEnumerator.Current + object? IEnumerator.Current // ReSharper disable once HeapView.PossibleBoxingAllocation => selector.Invoke(source![index]); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() - => ++index <= end; + { + if (index <= end) + { + index++; + return index <= end; + } + return false; + } [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation @@ -170,107 +181,121 @@ public bool Any() where TSelector2 : struct, IFunction => source.SelectAt>(new SelectorSelectorAtCombination(this.selector, selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - #endregion #region Element [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option ElementAt(int index) - => ((ReadOnlySpan)source.AsSpan()).ElementAt(index, selector); + => source.AsReadOnlySpan().ElementAt(index, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option First() - => ((ReadOnlySpan)source.AsSpan()).First(selector); + => source.AsReadOnlySpan().First(selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option Single() - => ((ReadOnlySpan)source.AsSpan()).Single(selector); + => source.AsReadOnlySpan().Single(selector); #endregion #region Conversion [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult[] ToArray() - => ((ReadOnlySpan)source.AsSpan()).ToArray(selector); + => source.AsReadOnlySpan().ToArray(selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => ((ReadOnlySpan)source.AsSpan()).ToArray(selector, pool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ((ReadOnlySpan)source.AsSpan()).ToArray(pool, clearOnDispose, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List ToList() - => ((ReadOnlySpan)source.AsSpan()).ToList(selector); + => source.AsReadOnlySpan().ToList(selector); #endregion } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ArraySegmentSelectEnumerable source) + public static int Count(this ArraySegmentSelectEnumerable source, TPredicate predicate = default) where TSelector : struct, IFunction - => source.Count; + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.Count, ArraySegmentSelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountAt(this ArraySegmentSelectEnumerable source, TPredicate predicate = default) + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.CountAt, ArraySegmentSelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentSelectEnumerable source) + where TSelector : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentSelectEnumerable source) + where TSelector : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentSelectEnumerable source) + where TSelector : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentSelectEnumerable source) + where TSelector : struct, IFunction + => source.source.AsReadOnlySpan().Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Sum(this ArraySegmentSelectEnumerable source) where TSelector : struct, IFunction - => ((ReadOnlySpan)source.source.AsSpan()).Sum(source.selector); + => source.source.AsReadOnlySpan().Sum(source.selector); } } diff --git a/NetFabric.Hyperlinq/Projection/Select/Select.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.AsyncValueEnumerable.cs similarity index 55% rename from NetFabric.Hyperlinq/Projection/Select/Select.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.AsyncValueEnumerable.cs index cc90a496f..cf9417147 100644 --- a/NetFabric.Hyperlinq/Projection/Select/Select.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.AsyncValueEnumerable.cs @@ -12,13 +12,6 @@ namespace NetFabric.Hyperlinq public static partial class AsyncValueEnumerableExtensions { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.AsyncFunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectEnumerable> Select(this TEnumerable source, Func> selector) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - => source.Select>(new AsyncFunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SelectEnumerable Select(this TEnumerable source, TSelector selector = default) where TEnumerable : IAsyncValueEnumerable @@ -26,7 +19,6 @@ public static partial class AsyncValueEnumerableExtensions where TSelector : struct, IAsyncFunction => new(in source, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public readonly partial struct SelectEnumerable : IAsyncValueEnumerable.Enumerator> @@ -34,16 +26,17 @@ public static partial class AsyncValueEnumerableExtensions where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction { - readonly TEnumerable source; - readonly TSelector selector; + internal readonly TEnumerable source; + internal readonly TSelector selector; internal SelectEnumerable(in TEnumerable source, TSelector selector) => (this.source, this.selector) = (source, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this, cancellationToken); @@ -52,15 +45,18 @@ public struct Enumerator : IAsyncEnumerator , IAsyncStateMachine { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier readonly CancellationToken cancellationToken; int state; AsyncValueTaskMethodBuilder builder; +#pragma warning disable IDE1006 // Naming Styles bool s__1; TResult? s__2; +#pragma warning restore IDE1006 // Naming Styles ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__2; ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__3; @@ -212,20 +208,12 @@ public ValueTask AnyAsync(CancellationToken cancellationToken = default) #endregion #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectEnumerable, TSource, TResult, TResult2>> Select(Func> selector) - => Select>(new AsyncFunctionWrapper(selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public SelectEnumerable> Select(TSelector2 selector = default) where TSelector2 : struct, IAsyncFunction => source.Select>(new AsyncSelectorSelectorCombination(this.selector, selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func> selector) - => SelectAt>(new AsyncFunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public SelectAtEnumerable> SelectAt(TSelector2 selector = default) where TSelector2 : struct, IAsyncFunction @@ -236,33 +224,131 @@ public ValueTask AnyAsync(CancellationToken cancellationToken = default) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ElementAtAsync(int index, CancellationToken cancellationToken = default) - => source.ElementAtAsync(index, selector, cancellationToken); + => source.ElementAtAsync(index, cancellationToken, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> FirstAsync(CancellationToken cancellationToken = default) - => source.FirstAsync(selector, cancellationToken); + => source.FirstAsync(cancellationToken, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> SingleAsync(CancellationToken cancellationToken = default) - => source.SingleAsync(selector, cancellationToken); + => source.SingleAsync(cancellationToken, selector); #endregion #region Conversion [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask ToArrayAsync(CancellationToken cancellationToken = default) - => source.ToArrayAsync(selector, cancellationToken); + => source.ToArrayAsync(cancellationToken, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToArrayAsync(MemoryPool pool, CancellationToken cancellationToken = default) - => source.ToArrayAsync(selector, pool, cancellationToken); + public ValueTask> ToArrayAsync(ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) + => source.ToArrayAsync(pool, cancellationToken, clearOnDispose, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToListAsync(CancellationToken cancellationToken = default) - => source.ToListAsync(selector, cancellationToken); + => source.ToListAsync(cancellationToken, selector); #endregion } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAsync(cancellationToken, source.selector); } } diff --git a/NetFabric.Hyperlinq/Projection/Select/Select.ReadOnlyMemory.cs b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ReadOnlyMemory.cs similarity index 77% rename from NetFabric.Hyperlinq/Projection/Select/Select.ReadOnlyMemory.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ReadOnlyMemory.cs index ebbaa8259..6b7094a0f 100644 --- a/NetFabric.Hyperlinq/Projection/Select/Select.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ReadOnlyMemory.cs @@ -11,17 +11,15 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemorySelectEnumerable> Select(this ReadOnlyMemory source, Func selector) + static MemorySelectEnumerable> Select(this ReadOnlyMemory source, Func selector) => source.Select>(new FunctionWrapper(selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemorySelectEnumerable Select(this ReadOnlyMemory source, TSelector selector = default) + static MemorySelectEnumerable Select(this ReadOnlyMemory source, TSelector selector = default) where TSelector : struct, IFunction => new(source, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public partial struct MemorySelectEnumerable : IValueReadOnlyList.Enumerator> @@ -73,6 +71,9 @@ internal MemorySelectEnumerable(ReadOnlyMemory source, TSelector select public void CopyTo(Span span) { + if (Count is 0) + return; + if (span.Length < Count) Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); @@ -80,7 +81,7 @@ public void CopyTo(Span span) } void ICollection.CopyTo(TResult[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); + => CopyTo(array.AsSpan(arrayIndex)); void ICollection.Add(TResult item) => Throw.NotSupportedException(); @@ -91,7 +92,7 @@ public bool Contains(TResult item) bool ICollection.Remove(TResult item) => Throw.NotSupportedException(); int IList.IndexOf(TResult item) - => ArrayExtensions.IndexOf(source.Span, item, selector); + => ArrayExtensions.IndexOf(source.Span, item, selector); void IList.Insert(int index, TResult item) => Throw.NotSupportedException(); void IList.RemoveAt(int index) @@ -102,7 +103,9 @@ public struct Enumerator : IEnumerator { readonly ReadOnlyMemory source; +#pragma warning disable IDE0044 // Add readonly modifier TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier int index; internal Enumerator(in MemorySelectEnumerable enumerable) @@ -112,14 +115,12 @@ internal Enumerator(in MemorySelectEnumerable enume index = -1; } - public readonly TResult Current + public TResult Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => selector.Invoke(source.Span[index]); } - readonly TResult IEnumerator.Current - => selector.Invoke(source.Span[index]); - readonly object? IEnumerator.Current + object? IEnumerator.Current // ReSharper disable once HeapView.PossibleBoxingAllocation => selector.Invoke(source.Span[index]); @@ -128,10 +129,11 @@ public bool MoveNext() => ++index < source.Length; [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation @@ -167,19 +169,6 @@ public bool Any() where TSelector2 : struct, IFunction => source.SelectAt>(new SelectorSelectorAtCombination(this.selector, selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => ReadOnlyListExtensions.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => ReadOnlyListExtensions.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(this, selector); - #endregion #region Element @@ -202,41 +191,26 @@ public TResult[] ToArray() => source.Span.ToArray(selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.Span.ToArray(selector, pool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.Span.ToArray(pool, clearOnDispose, selector); public List ToList() => source.Span.ToList(selector); #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this MemorySelectEnumerable source) + public static int Count(this MemorySelectEnumerable source, TPredicate predicate = default) where TSelector : struct, IFunction - => source.Count; + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.Count, MemorySelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountAt(this MemorySelectEnumerable source, TPredicate predicate = default) + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.CountAt, MemorySelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this MemorySelectEnumerable source) @@ -248,6 +222,26 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer where TSelector : struct, IFunction => source.source.Span.Sum(source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemorySelectEnumerable source) + where TSelector : struct, IFunction + => source.source.Span.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemorySelectEnumerable source) + where TSelector : struct, IFunction + => source.source.Span.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemorySelectEnumerable source) + where TSelector : struct, IFunction + => source.source.Span.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemorySelectEnumerable source) + where TSelector : struct, IFunction + => source.source.Span.Sum(source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this MemorySelectEnumerable source) where TSelector : struct, IFunction diff --git a/NetFabric.Hyperlinq/Projection/Select/Select.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ReadOnlySpan.cs similarity index 69% rename from NetFabric.Hyperlinq/Projection/Select/Select.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ReadOnlySpan.cs index 04e3c0dff..81181db8a 100644 --- a/NetFabric.Hyperlinq/Projection/Select/Select.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ReadOnlySpan.cs @@ -1,7 +1,6 @@ using System; using System.Buffers; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -10,17 +9,15 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectEnumerable> Select(this ReadOnlySpan source, Func selector) + static SpanSelectEnumerable> Select(this ReadOnlySpan source, Func selector) => source.Select>(new FunctionWrapper(selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectEnumerable Select(this ReadOnlySpan source, TSelector selector = default) + static SpanSelectEnumerable Select(this ReadOnlySpan source, TSelector selector = default) where TSelector : struct, IFunction => new(source, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public ref struct SpanSelectEnumerable where TSelector : struct, IFunction @@ -102,15 +99,15 @@ public TResult[] ToArray() => source.ToArray(selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.ToArray(selector, pool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArray(pool, clearOnDispose, selector); public List ToList() => source.ToList(selector); #endregion - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) + public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) { comparer ??= EqualityComparer.Default; @@ -133,10 +130,47 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer } } + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public static int Count(this SpanSelectEnumerable source, Func predicate) + // where TSelector : struct, IFunction + // => ValueReadOnlyCollectionExtensions.Count, SpanSelectEnumerable.Enumerator, TResult>(source, predicate); + // + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public static int Count(this SpanSelectEnumerable source, TPredicate predicate = default) + // where TSelector : struct, IFunction + // where TPredicate : struct, IFunction + // => ValueReadOnlyCollectionExtensions.Count, SpanSelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + // + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public static int Count(this SpanSelectEnumerable source, Func predicate) + // where TSelector : struct, IFunction + // => ValueReadOnlyCollectionExtensions.Count, SpanSelectEnumerable.Enumerator, TResult>(source, predicate); + // + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public static int CountAt(this SpanSelectEnumerable source, TPredicate predicate = default) + // where TSelector : struct, IFunction + // where TPredicate : struct, IFunction + // => ValueReadOnlyCollectionExtensions.CountAt, SpanSelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this SpanSelectEnumerable source) - where TSelector : struct, IFunction - => source.Count; + public static nint Sum(this SpanSelectEnumerable source) + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanSelectEnumerable source) + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanSelectEnumerable source) + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanSelectEnumerable source) + where TSelector : struct, IFunction + => source.source.Sum(source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this SpanSelectEnumerable source) diff --git a/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ValueEnumerable.cs new file mode 100644 index 000000000..f45fc6316 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ValueEnumerable.cs @@ -0,0 +1,249 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueEnumerableExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SelectEnumerable Select(this TEnumerable source, TSelector selector = default) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(in source, selector); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct SelectEnumerable + : IValueEnumerable.Enumerator> + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + internal readonly TEnumerable source; + internal readonly TSelector selector; + + internal SelectEnumerable(in TEnumerable source, TSelector selector) + => (this.source, this.selector) = (source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + => new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; + TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier + + internal Enumerator(in SelectEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + selector = enumerable.selector; + } + + public TResult Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => selector.Invoke(enumerator.Current); + } + object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => selector.Invoke(enumerator.Current); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + => enumerator.MoveNext(); + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public void Dispose() + => enumerator.Dispose(); + } + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => source.Count(); + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => source.Any(); + + #endregion + #region Filtering + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectEnumerable> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => source.Select>(new SelectorSelectorCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectAtEnumerable> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => source.SelectAt>(new SelectorSelectorAtCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector2 : struct, IFunction + => this.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => source.ElementAt(index, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => source.First(selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => source.Single(selector); + + #endregion + #region Conversion + + public TResult[] ToArray() + => source.ToArray(selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArray(pool, clearOnDispose, selector); + + public List ToList() + => source.ToList(selector); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.Sum(source.selector); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ValueReadOnlyCollection.cs new file mode 100644 index 000000000..b472b0695 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ValueReadOnlyCollection.cs @@ -0,0 +1,294 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyCollectionExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SelectEnumerable Select(this TEnumerable source, TSelector selector = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(in source, selector); + + [StructLayout(LayoutKind.Auto)] + public partial struct SelectEnumerable + : IValueReadOnlyCollection.Enumerator> + , ICollection + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + internal readonly TEnumerable source; + internal TSelector selector; + + internal SelectEnumerable(in TEnumerable source, TSelector selector) + => (this.source, this.selector) = (source, selector); + + public readonly int Count + => source.Count; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Enumerator GetEnumerator() + => new(in this); + readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + bool ICollection.IsReadOnly + => true; + + public void CopyTo(Span span) + { + if (Count is 0) + return; + + if (span.Length < Count) + Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); + + checked + { + using var enumerator = source.GetEnumerator(); + for (var index = 0; enumerator.MoveNext(); index++) + span[index] = selector.Invoke(enumerator.Current); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(TResult[] array, int arrayIndex) + => CopyTo(array.AsSpan(arrayIndex)); + + public bool Contains(TResult item) + => ValueReadOnlyCollectionExtensions.Contains(source, item, default, selector); + + [ExcludeFromCodeCoverage] + void ICollection.Add(TResult item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + void ICollection.Clear() + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + bool ICollection.Remove(TResult item) + => Throw.NotSupportedException(); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; + TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier + + internal Enumerator(in SelectEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + selector = enumerable.selector; + } + + public TResult Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => selector.Invoke(enumerator.Current); + } + object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => selector.Invoke(enumerator.Current); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + => enumerator.MoveNext(); + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public void Dispose() + => enumerator.Dispose(); + } + + #region Aggregation + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => source.Count is not 0; + + #endregion + #region Filtering + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectEnumerable> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.Select>(source, new SelectorSelectorCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectAtEnumerable> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.SelectAt>(source, new SelectorSelectorAtCombination(this.selector, selector)); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => ValueReadOnlyCollectionExtensions.ElementAt(source, index, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => ValueReadOnlyCollectionExtensions.First(source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => ValueReadOnlyCollectionExtensions.Single(source, selector); + + #endregion + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TResult[] ToArray() + => ValueReadOnlyCollectionExtensions.ToArray(source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ValueReadOnlyCollectionExtensions.ToArray(source, pool, clearOnDispose, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public List ToList() + => ValueReadOnlyCollectionExtensions.ToList(source, selector); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(this SelectEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => Count, SelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountAt(this SelectEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => CountAt, SelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => Sum(source.source, source.selector); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ValueReadOnlyList.cs new file mode 100644 index 000000000..9966ada5c --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/Select/Select/Select.ValueReadOnlyList.cs @@ -0,0 +1,325 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SelectEnumerable> Select(this TEnumerable source, Func selector) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => Select>(source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SelectEnumerable Select(this TEnumerable source, TSelector selector = default) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(in source, selector); + + [StructLayout(LayoutKind.Auto)] + public partial struct SelectEnumerable + : IValueReadOnlyList.Enumerator> + , IList + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + internal TEnumerable source; + internal TSelector selector; + + internal SelectEnumerable(in TEnumerable source, TSelector selector) + => (this.source, this.selector) = (source, selector); + + public readonly int Count + => source.Count; + + public TResult this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + ThrowIfArgument.OutOfRange(index, Count, nameof(index)); + return selector.Invoke(source[index]); + } + } + TResult IList.this[int index] + { + get => this[index]; + + [ExcludeFromCodeCoverage] + // ReSharper disable once ValueParameterNotUsed + set => Throw.NotSupportedException(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Enumerator GetEnumerator() + => new(in this); + readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + + bool ICollection.IsReadOnly + => true; + + public readonly void CopyTo(Span span) + { + if (span.Length < Count) + Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); + + ValueReadOnlyCollectionExtensions.Copy(source, span, selector); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly void CopyTo(TResult[] array, int arrayIndex) + => CopyTo(array.AsSpan(arrayIndex)); + + public readonly bool Contains(TResult item) + => ValueReadOnlyCollectionExtensions.Contains(source, item, default, selector); + + public readonly int IndexOf(TResult item) + => ValueReadOnlyCollectionExtensions.IndexOf(source, item, selector); + + [ExcludeFromCodeCoverage] + readonly void ICollection.Add(TResult item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + readonly void ICollection.Clear() + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + readonly bool ICollection.Remove(TResult item) + => Throw.NotSupportedException(); + + [ExcludeFromCodeCoverage] + readonly void IList.Insert(int index, TResult item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + readonly void IList.RemoveAt(int index) + => Throw.NotSupportedException(); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; + TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier + + internal Enumerator(in SelectEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + selector = enumerable.selector; + } + + public TResult Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => selector.Invoke(enumerator.Current); + } + object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => selector.Invoke(enumerator.Current); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + => enumerator.MoveNext(); + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public void Dispose() + => enumerator.Dispose(); + } + + #region Partitioning + + #endregion + #region Aggregation + + #endregion + #region Quantifier + + #endregion + #region Filtering + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectEnumerable> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueReadOnlyListExtensions.Select>(source, new SelectorSelectorCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectAtEnumerable> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueReadOnlyListExtensions.SelectAt>(source, new SelectorSelectorAtCombination(this.selector, selector)); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Option ElementAt(int index) + => source.ElementAt(index, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Option First() + => source.First(selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Option Single() + => source.Single(selector); + + #endregion + #region Conversion + + public readonly SelectEnumerable AsValueEnumerable() + => this; + + public readonly SelectEnumerable AsEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly TResult[] ToArray() + => source.ToArray(selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArray(pool, clearOnDispose, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly List ToList() + => source.ToList(selector); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(this SelectEnumerable source, TPredicate predicate = default) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.Count, SelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountAt(this SelectEnumerable source, TPredicate predicate = default) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.CountAt, SelectEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.Sum(source.source, source.selector); + } +} diff --git a/NetFabric.Hyperlinq/Projection/Select/SelectEnumerator.cs b/NetFabric.Hyperlinq.Core/Projection/Select/Select/SelectEnumerator.cs similarity index 100% rename from NetFabric.Hyperlinq/Projection/Select/SelectEnumerator.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/Select/SelectEnumerator.cs diff --git a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ArraySegment.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ArraySegment.cs similarity index 73% rename from NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ArraySegment.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ArraySegment.cs index 5abda5ee6..8a86230a4 100644 --- a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ArraySegment.cs +++ b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ArraySegment.cs @@ -10,17 +10,16 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] + [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectAtEnumerable> Select(this in ArraySegment source, Func selector) + static ArraySegmentSelectAtEnumerable> Select(this in ArraySegment source, Func selector) => source.SelectAt>(new FunctionWrapper(selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectAtEnumerable SelectAt(this in ArraySegment source, TSelector selector = default) + static ArraySegmentSelectAtEnumerable SelectAt(this in ArraySegment source, TSelector selector = default) where TSelector : struct, IFunction => new(in source, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public partial struct ArraySegmentSelectAtEnumerable : IValueReadOnlyList.Enumerator> @@ -37,15 +36,17 @@ internal ArraySegmentSelectAtEnumerable(in ArraySegment source, TSelect } public readonly int Count - => source.Count; + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source.Count; + } public TResult this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if (index < 0 || index >= source.Count) Throw.IndexOutOfRangeException(); - + ThrowIfArgument.OutOfRange(index, Count, nameof(index)); return selector.Invoke(source.Array![index + source.Offset], index); } } @@ -83,11 +84,11 @@ void ICollection.Add(TResult item) void ICollection.Clear() => Throw.NotSupportedException(); public bool Contains(TResult item) - => ((ReadOnlySpan)source.AsSpan()).ContainsAt(item, default, selector); + => source.AsReadOnlySpan().ContainsAt(item, default, selector); bool ICollection.Remove(TResult item) => Throw.NotSupportedException(); int IList.IndexOf(TResult item) - => ArrayExtensions.IndexOfAt(source, item, selector); + => IndexOfAt(source, item, selector); void IList.Insert(int index, TResult item) => Throw.NotSupportedException(); @@ -99,7 +100,9 @@ public struct Enumerator : IEnumerator { readonly TSource[]? source; +#pragma warning disable IDE0044 // Add readonly modifier TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier readonly int offset; readonly int end; int index; @@ -113,23 +116,29 @@ internal Enumerator(in ArraySegmentSelectAtEnumerable selector.Invoke(source![index + offset], index); - readonly TResult IEnumerator.Current - => selector.Invoke(source![index + offset], index)!; - readonly object? IEnumerator.Current + object? IEnumerator.Current // ReSharper disable once HeapView.PossibleBoxingAllocation => selector.Invoke(source![index + offset], index); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() - => ++index <= end; - + { + if (index <= end) + { + index++; + return index <= end; + } + return false; + } + [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation @@ -165,78 +174,50 @@ public bool Any() where TSelector2 : struct, IFunction => source.SelectAt>(new SelectorAtSelectorAtCombination(this.selector, selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - #endregion #region Element [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option ElementAt(int index) - => ((ReadOnlySpan)source.AsSpan()).ElementAtAt(index, selector); + => source.AsReadOnlySpan().ElementAtAt(index, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option First() - => ((ReadOnlySpan)source.AsSpan()).FirstAt(selector); + => source.AsReadOnlySpan().FirstAt(selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public Option Single() - => ((ReadOnlySpan)source.AsSpan()).SingleAt(selector); + => source.AsReadOnlySpan().SingleAt(selector); #endregion #region Conversion [MethodImpl(MethodImplOptions.AggressiveInlining)] public TResult[] ToArray() - => ((ReadOnlySpan)source.AsSpan()).ToArrayAt(selector); + => source.AsReadOnlySpan().ToArrayAt(selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => ((ReadOnlySpan)source.AsSpan()).ToArrayAt(selector, pool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ((ReadOnlySpan)source.AsSpan()).ToArrayAt(pool, clearOnDispose, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List ToList() - => ((ReadOnlySpan)source.AsSpan()).ToListAt(selector); + => source.AsReadOnlySpan().ToListAt(selector); #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ArraySegmentSelectAtEnumerable source) + public static int Count(this ArraySegmentSelectAtEnumerable source, TPredicate predicate = default) + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.Count, ArraySegmentSelectAtEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountAt(this ArraySegmentSelectAtEnumerable source, TPredicate predicate = default) where TSelector : struct, IFunction - => source.Count; + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.CountAt, ArraySegmentSelectAtEnumerable.Enumerator, TResult, TPredicate>(source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this ArraySegmentSelectAtEnumerable source) @@ -248,6 +229,26 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer where TSelector : struct, IFunction => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentSelectAtEnumerable source) + where TSelector : struct, IFunction + => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentSelectAtEnumerable source) + where TSelector : struct, IFunction + => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentSelectAtEnumerable source) + where TSelector : struct, IFunction + => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentSelectAtEnumerable source) + where TSelector : struct, IFunction + => ((ReadOnlySpan)source.source.AsSpan()).SumAt(source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this ArraySegmentSelectAtEnumerable source) where TSelector : struct, IFunction diff --git a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.AsyncValueEnumerable.cs similarity index 55% rename from NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.AsyncValueEnumerable.cs index cfb04e7d7..d4b1152cd 100644 --- a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.AsyncValueEnumerable.cs @@ -12,13 +12,6 @@ namespace NetFabric.Hyperlinq public static partial class AsyncValueEnumerableExtensions { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.AsyncFunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectAtEnumerable> Select(this TEnumerable source, Func> selector) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - => source.SelectAt>(new AsyncFunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SelectAtEnumerable SelectAt(this TEnumerable source, TSelector selector = default) where TEnumerable : IAsyncValueEnumerable @@ -26,7 +19,6 @@ public static partial class AsyncValueEnumerableExtensions where TSelector : struct, IAsyncFunction => new(in source, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public readonly partial struct SelectAtEnumerable : IAsyncValueEnumerable.Enumerator> @@ -34,16 +26,17 @@ public static partial class AsyncValueEnumerableExtensions where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction { - readonly TEnumerable source; - readonly TSelector selector; + internal readonly TEnumerable source; + internal readonly TSelector selector; internal SelectAtEnumerable(in TEnumerable source, TSelector selector) => (this.source, this.selector) = (source, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this, cancellationToken); @@ -52,16 +45,19 @@ public struct Enumerator : IAsyncEnumerator , IAsyncStateMachine { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier readonly CancellationToken cancellationToken; int index; int state; AsyncValueTaskMethodBuilder builder; +#pragma warning disable IDE1006 // Naming Styles bool s__1; TResult? s__2; +#pragma warning restore IDE1006 // Naming Styles ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__2; ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__3; @@ -214,20 +210,12 @@ public ValueTask AnyAsync(CancellationToken cancellationToken = default) #endregion #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func> selector) - => Select>(new AsyncFunctionWrapper(selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public SelectAtEnumerable> Select(TSelector2 selector = default) where TSelector2 : struct, IAsyncFunction => source.SelectAt>(new AsyncSelectorAtSelectorCombination(this.selector, selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func> selector) - => SelectAt>(new AsyncFunctionWrapper(selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public SelectAtEnumerable> SelectAt(TSelector2 selector = default) where TSelector2 : struct, IAsyncFunction @@ -238,33 +226,131 @@ public ValueTask AnyAsync(CancellationToken cancellationToken = default) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ElementAtAsync(int index, CancellationToken cancellationToken = default) - => source.ElementAtAtAsync(index, selector, cancellationToken); + => source.ElementAtAtAsync(index, cancellationToken, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> FirstAsync(CancellationToken cancellationToken = default) - => source.FirstAtAsync(selector, cancellationToken); + => source.FirstAtAsync(cancellationToken, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> SingleAsync(CancellationToken cancellationToken = default) - => source.SingleAtAsync(selector, cancellationToken); + => source.SingleAtAsync(cancellationToken, selector); #endregion #region Conversion [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask ToArrayAsync(CancellationToken cancellationToken = default) - => source.ToArrayAtAsync(selector, cancellationToken); + => source.ToArrayAtAsync(cancellationToken, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToArrayAsync(MemoryPool pool, CancellationToken cancellationToken = default) - => source.ToArrayAtAsync(selector, pool, cancellationToken); + public ValueTask> ToArrayAsync(ArrayPool pool, CancellationToken cancellationToken = default, bool clearOnDispose = default) + => source.ToArrayAtAsync(pool, cancellationToken, clearOnDispose, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask> ToListAsync(CancellationToken cancellationToken = default) - => source.ToListAtAsync(selector, cancellationToken); + => source.ToListAtAsync(cancellationToken, selector); #endregion } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SelectAtEnumerable source, CancellationToken cancellationToken = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + where TSelector : struct, IAsyncFunction + => source.source.SumAtAsync(cancellationToken, source.selector); } } diff --git a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ReadOnlyMemory.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ReadOnlyMemory.cs similarity index 75% rename from NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ReadOnlyMemory.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ReadOnlyMemory.cs index 7a9d86722..b67c20fec 100644 --- a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ReadOnlyMemory.cs @@ -11,17 +11,15 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemorySelectAtEnumerable> Select(this ReadOnlyMemory source, Func selector) + static MemorySelectAtEnumerable> Select(this ReadOnlyMemory source, Func selector) => source.SelectAt>(new FunctionWrapper(selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemorySelectAtEnumerable SelectAt(this ReadOnlyMemory source, TSelector selector = default) + static MemorySelectAtEnumerable SelectAt(this ReadOnlyMemory source, TSelector selector = default) where TSelector : struct, IFunction => new(source, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public partial struct MemorySelectAtEnumerable : IValueReadOnlyList.Enumerator> @@ -46,7 +44,7 @@ internal MemorySelectAtEnumerable(ReadOnlyMemory source, TSelector sele get => selector.Invoke(source.Span[index], index); } TResult IReadOnlyList.this[int index] - => this[index]!; + => this[index]; TResult IList.this[int index] { get => this[index]; @@ -74,21 +72,22 @@ void ICollection.CopyTo(TResult[] array, int arrayAt) { var span = source.Span; for (var index = 0; index < span.Length; index++) - array[index + arrayAt] = selector.Invoke(span[index], index)!; + array[index + arrayAt] = selector.Invoke(span[index], index); } - void ICollection.Add(TResult item) + + readonly void ICollection.Add(TResult item) => Throw.NotSupportedException(); - void ICollection.Clear() + readonly void ICollection.Clear() => Throw.NotSupportedException(); - public bool Contains(TResult item) + public readonly bool Contains(TResult item) => source.Span.ContainsAt(item, default, selector); - bool ICollection.Remove(TResult item) + readonly bool ICollection.Remove(TResult item) => Throw.NotSupportedException(); - int IList.IndexOf(TResult item) - => ArrayExtensions.IndexOfAt(source.Span, item, selector); - void IList.Insert(int index, TResult item) + readonly int IList.IndexOf(TResult item) + => IndexOfAt(source.Span, item, selector); + readonly void IList.Insert(int index, TResult item) => Throw.NotSupportedException(); - void IList.RemoveAt(int index) + readonly void IList.RemoveAt(int index) => Throw.NotSupportedException(); [StructLayout(LayoutKind.Auto)] @@ -96,7 +95,9 @@ public struct Enumerator : IEnumerator { readonly ReadOnlyMemory source; +#pragma warning disable IDE0044 // Add readonly modifier TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier int index; internal Enumerator(in MemorySelectAtEnumerable enumerable) @@ -111,21 +112,20 @@ internal Enumerator(in MemorySelectAtEnumerable enu [MethodImpl(MethodImplOptions.AggressiveInlining)] get => selector.Invoke(source.Span[index], index); } - readonly TResult IEnumerator.Current - => selector.Invoke(source.Span[index], index)!; - readonly object? IEnumerator.Current + object? IEnumerator.Current // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(source.Span[index], index)!; + => selector.Invoke(source.Span[index], index); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() => ++index < source.Length; [ExcludeFromCodeCoverage] + [DoesNotReturn] public readonly void Reset() => Throw.NotSupportedException(); - public void Dispose() { } + public readonly void Dispose() { } } #region Aggregation @@ -161,19 +161,6 @@ public bool Any() where TSelector2 : struct, IFunction => source.SelectAt>(new SelectorAtSelectorAtCombination(this.selector, selector)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - #endregion #region Element @@ -196,41 +183,26 @@ public TResult[] ToArray() => source.Span.ToArrayAt(selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.Span.ToArrayAt(selector, pool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.Span.ToArrayAt(pool, clearOnDispose, selector); public List ToList() => source.Span.ToListAt(selector); #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this MemorySelectAtEnumerable source) + public static int Count(this MemorySelectAtEnumerable source, TPredicate predicate = default) + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => source.Count(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountAt(this MemorySelectAtEnumerable source, TPredicate predicate = default) where TSelector : struct, IFunction - => source.Count; + where TPredicate : struct, IFunction + => source.CountAt(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this MemorySelectAtEnumerable source) @@ -242,6 +214,26 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer where TSelector : struct, IFunction => source.source.Span.SumAt(source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemorySelectAtEnumerable source) + where TSelector : struct, IFunction + => source.source.Span.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemorySelectAtEnumerable source) + where TSelector : struct, IFunction + => source.source.Span.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemorySelectAtEnumerable source) + where TSelector : struct, IFunction + => source.source.Span.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemorySelectAtEnumerable source) + where TSelector : struct, IFunction + => source.source.Span.SumAt(source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this MemorySelectAtEnumerable source) where TSelector : struct, IFunction diff --git a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ReadOnlySpan.cs similarity index 72% rename from NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ReadOnlySpan.cs index 8da5a17f3..77490c8b0 100644 --- a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ReadOnlySpan.cs @@ -1,7 +1,6 @@ using System; using System.Buffers; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -10,17 +9,15 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectAtEnumerable> Select(this ReadOnlySpan source, Func selector) + static SpanSelectAtEnumerable> Select(this ReadOnlySpan source, Func selector) => source.SelectAt>(new FunctionWrapper(selector)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectAtEnumerable SelectAt(this ReadOnlySpan source, TSelector selector = default) + static SpanSelectAtEnumerable SelectAt(this ReadOnlySpan source, TSelector selector = default) where TSelector : struct, IFunction => new(source, selector); - [GeneratorMapping("TSource", "TResult")] [StructLayout(LayoutKind.Auto)] public ref struct SpanSelectAtEnumerable where TSelector : struct, IFunction @@ -102,15 +99,15 @@ public TResult[] ToArray() => source.ToArrayAt(selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.ToArrayAt(selector, pool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArrayAt(pool, clearOnDispose, selector); public List ToList() => source.ToListAt(selector); #endregion - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) + public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) { comparer ??= EqualityComparer.Default; @@ -133,10 +130,27 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this SpanSelectAtEnumerable source) - where TSelector : struct, IFunction - => source.Count; + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public static int Count(this SpanSelectAtEnumerable source, Func predicate) + // where TSelector : struct, IFunction + // => source.Count(predicate); + // + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public static int Count(this SpanSelectAtEnumerable source, TPredicate predicate = default) + // where TSelector : struct, IFunction + // where TPredicate : struct, IFunction + // => source.Count(predicate); + // + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public static int Count(this SpanSelectAtEnumerable source, Func predicate) + // where TSelector : struct, IFunction + // => source.Count(predicate); + // + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public static int CountAt(this SpanSelectAtEnumerable source, TPredicate predicate = default) + // where TSelector : struct, IFunction + // where TPredicate : struct, IFunction + // => source.CountAt(predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sum(this SpanSelectAtEnumerable source) @@ -148,6 +162,26 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer where TSelector : struct, IFunction => source.source.SumAt(source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanSelectAtEnumerable source) + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanSelectAtEnumerable source) + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanSelectAtEnumerable source) + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SpanSelectAtEnumerable source) + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this SpanSelectAtEnumerable source) where TSelector : struct, IFunction diff --git a/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ValueEnumerable.cs new file mode 100644 index 000000000..6ce156e76 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ValueEnumerable.cs @@ -0,0 +1,259 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueEnumerableExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SelectAtEnumerable SelectAt(this TEnumerable source, TSelector selector = default) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(in source, selector); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct SelectAtEnumerable + : IValueEnumerable.Enumerator> + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + internal readonly TEnumerable source; + internal readonly TSelector selector; + + internal SelectAtEnumerable(in TEnumerable source, TSelector selector) + => (this.source, this.selector) = (source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + => new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; + TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier + int index; + + internal Enumerator(in SelectAtEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + selector = enumerable.selector; + index = -1; + } + + public readonly TResult Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => selector.Invoke(enumerator.Current, index); + } + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => selector.Invoke(enumerator.Current, index); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + if (enumerator.MoveNext()) + { + checked { index++; } + return true; + } + return false; + } + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public void Dispose() + => enumerator.Dispose(); + } + + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => source.Count(); + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => source.Any(); + + #endregion + #region Filtering + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectAtEnumerable> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => source.SelectAt>(new SelectorAtSelectorCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectAtEnumerable> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => source.SelectAt>(new SelectorAtSelectorAtCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector2 : struct, IFunction + => this.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => source.ElementAtAt(index, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => source.FirstAt(selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => source.SingleAt(selector); + + #endregion + #region Conversion + + public TResult[] ToArray() + => source.ToArrayAt(selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArrayAt(pool, clearOnDispose, selector); + + public List ToList() + => source.ToListAt(selector); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectAtEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.source.SumAt(source.selector); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ValueReadOnlyCollection.cs new file mode 100644 index 000000000..98f68523f --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ValueReadOnlyCollection.cs @@ -0,0 +1,303 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyCollectionExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SelectAtEnumerable SelectAt(this TEnumerable source, TSelector selector = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(in source, selector); + + [StructLayout(LayoutKind.Auto)] + public partial struct SelectAtEnumerable + : IValueReadOnlyCollection.Enumerator> + , ICollection + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + internal readonly TEnumerable source; + internal TSelector selector; + + internal SelectAtEnumerable(in TEnumerable source, TSelector selector) + => (this.source, this.selector) = (source, selector); + + public readonly int Count + => source.Count; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Enumerator GetEnumerator() + => new(in this); + readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + bool ICollection.IsReadOnly + => true; + + public void CopyTo(Span span) + { + if (Count is 0) + return; + + if (span.Length < Count) + Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); + + checked + { + using var enumerator = source.GetEnumerator(); + for (var index = 0; enumerator.MoveNext(); index++) + span[index] = selector.Invoke(enumerator.Current, index); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(TResult[] array, int arrayIndex) + => CopyTo(array.AsSpan(arrayIndex)); + + public bool Contains(TResult item) + => ContainsAt(source, item, default, selector); + + [ExcludeFromCodeCoverage] + void ICollection.Add(TResult item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + void ICollection.Clear() + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + bool ICollection.Remove(TResult item) + => Throw.NotSupportedException(); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; + TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier + int index; + + internal Enumerator(in SelectAtEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + selector = enumerable.selector; + index = -1; + } + + public TResult Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => selector.Invoke(enumerator.Current, index); + } + object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => selector.Invoke(enumerator.Current, index); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + if (enumerator.MoveNext()) + { + checked { index++; } + return true; + } + return false; + } + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public readonly void Dispose() + => enumerator.Dispose(); + } + + #region Aggregation + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => source.Count is not 0; + + #endregion + #region Filtering + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectAtEnumerable> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.SelectAt>(source, new SelectorAtSelectorCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectAtEnumerable> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueReadOnlyCollectionExtensions.SelectAt>(source, new SelectorAtSelectorAtCombination(this.selector, selector)); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => ElementAtAt(source, index, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => FirstAt(source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => SingleAt(source, selector); + + #endregion + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TResult[] ToArray() + => ToArrayAt(source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ToArrayAt(source, pool, clearOnDispose, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public List ToList() + => ToListAt(source, selector); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(this SelectAtEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => Count, SelectAtEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountAt(this SelectAtEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => CountAt, SelectAtEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectAtEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ValueReadOnlyList.cs new file mode 100644 index 000000000..9d270ce69 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAt.ValueReadOnlyList.cs @@ -0,0 +1,341 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SelectAtEnumerable> Select(this TEnumerable source, Func selector) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => SelectAt>(source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SelectAtEnumerable SelectAt(this TEnumerable source, TSelector selector = default) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(in source, selector); + + [StructLayout(LayoutKind.Auto)] + public partial struct SelectAtEnumerable + : IValueReadOnlyList.Enumerator> + , IList + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + internal TEnumerable source; + internal TSelector selector; + + internal SelectAtEnumerable(in TEnumerable source, TSelector selector) + => (this.source, this.selector) = (source, selector); + + public int Count + => source.Count; + + public TResult this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + ThrowIfArgument.OutOfRange(index, Count, nameof(index)); + return selector.Invoke(source[index], index); + } + } + TResult IList.this[int index] + { + get => this[index]; + + [ExcludeFromCodeCoverage] + readonly + // ReSharper disable once ValueParameterNotUsed + set => Throw.NotSupportedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Enumerator GetEnumerator() + => new (in this); + readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => GetEnumerator(); + + bool ICollection.IsReadOnly + => true; + + public void CopyTo(Span span) + { + if (span.Length < Count) + Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); + + var end = Count; + for (var index = 0; index < end; index++) + { + var item = source[index]; + span[index] = selector.Invoke(item, index); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(TResult[] array, int arrayIndex) + => CopyTo(array.AsSpan(arrayIndex)); + + public readonly bool Contains(TResult item) + => ValueReadOnlyCollectionExtensions.ContainsAt(source, item, default, selector); + + public readonly int IndexOf(TResult item) + => ValueReadOnlyCollectionExtensions.IndexOfAt(source, item, selector); + + [ExcludeFromCodeCoverage] + void ICollection.Add(TResult item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + void ICollection.Clear() + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + bool ICollection.Remove(TResult item) + => Throw.NotSupportedException(); + + [ExcludeFromCodeCoverage] + void IList.Insert(int index, TResult item) + => Throw.NotSupportedException(); + [ExcludeFromCodeCoverage] + void IList.RemoveAt(int index) + => Throw.NotSupportedException(); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; + TSelector selector; +#pragma warning restore IDE0044 // Add readonly modifier + int index; + + internal Enumerator(in SelectAtEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + selector = enumerable.selector; + index = -1; + } + + public TResult Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => selector.Invoke(enumerator.Current, index); + } + object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => selector.Invoke(enumerator.Current, index); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + if (enumerator.MoveNext()) + { + checked { index++; } + return true; + } + return false; + } + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + // ReSharper disable once MA0102 + public void Dispose() + => enumerator.Dispose(); + } + + + #region Partitioning + + #endregion + #region Aggregation + + #endregion + #region Quantifier + + #endregion + #region Filtering + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly SelectAtEnumerable> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueReadOnlyListExtensions.SelectAt>(source, new SelectorAtSelectorCombination(this.selector, selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly SelectAtEnumerable> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueReadOnlyListExtensions.SelectAt>(source, new SelectorAtSelectorAtCombination(this.selector, selector)); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Option ElementAt(int index) + => source.ElementAtAt(index, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Option First() + => source.FirstAt(selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Option Single() + => source.SingleAt(selector); + + #endregion + #region Conversion + + public readonly SelectAtEnumerable AsValueEnumerable() + => this; + + public readonly SelectAtEnumerable AsEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly TResult[] ToArray() + => ValueReadOnlyCollectionExtensions.ToArrayAt(source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => ValueReadOnlyCollectionExtensions.ToArrayAt(source, pool, clearOnDispose, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly List ToList() + => ValueReadOnlyCollectionExtensions.ToListAt(source, selector); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(this SelectAtEnumerable source, TPredicate predicate = default) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.Count, SelectAtEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountAt(this SelectAtEnumerable source, TPredicate predicate = default) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.CountAt, SelectAtEnumerable.Enumerator, TResult, TPredicate>(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectAtEnumerable source) + where TEnumerable : struct, IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueReadOnlyCollectionExtensions.SumAt(source.source, source.selector); + } +} diff --git a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAtEnumerator.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAtEnumerator.cs similarity index 100% rename from NetFabric.Hyperlinq/Projection/SelectAt/SelectAtEnumerator.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/SelectAt/SelectAtEnumerator.cs diff --git a/NetFabric.Hyperlinq.Core/Projection/Select/SelectVector/SelectVector.Range.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectVector/SelectVector.Range.cs new file mode 100644 index 000000000..9da26df94 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/Select/SelectVector/SelectVector.Range.cs @@ -0,0 +1,150 @@ +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueEnumerable + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static RangeSelectVectorContext, Vector>, FunctionWrapper> SelectVector(int start, int count, Func, Vector> vectorSelector, Func selector) + where TResult : struct + => SelectVector, Vector>, FunctionWrapper>(start, count, new FunctionWrapper, Vector>(vectorSelector), new FunctionWrapper(selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static RangeSelectVectorContext SelectVector(int start, int count, TSelector selector = default) + where TSelector : struct, IFunction, Vector>, IFunction + where TResult : struct + => SelectVector(start, count, selector, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static RangeSelectVectorContext SelectVector(int start, int count, TVectorSelector vectorSelector = default, TSelector selector = default) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + where TResult : struct + => new(start, count, vectorSelector, selector); + + + [StructLayout(LayoutKind.Auto)] + public partial struct RangeSelectVectorContext + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + where TResult : struct + { + internal readonly int start; + internal readonly int count; + internal TVectorSelector vectorSelector; + internal TSelector selector; + + internal RangeSelectVectorContext(int start, int count, TVectorSelector vectorSelector, TSelector selector) + { + if (Vector.Count != Vector.Count) + Throw.NotSupportedException(); + + this.start = start; + this.count = count; + this.vectorSelector = vectorSelector; + this.selector = selector; + } + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => count; + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => count is not 0; + + #endregion + #region Filtering + + #endregion + #region Projection + + #endregion + #region Element + + #endregion + #region Conversion + + public TResult[] ToArray() + { + var result = Utils.AllocateUninitializedArray(count); + ArrayExtensions.CopyRange(start, count, result.AsSpan(), vectorSelector, selector); + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + { + var result = pool.Lease(count, clearOnDispose); + ArrayExtensions.CopyRange(start, count, result.Memory.Span, vectorSelector, selector); + return result; + } + + public List ToList() + => count switch + { + // ReSharper disable once HeapView.ObjectAllocation.Evident + 0 => new List(), + _ => ToArray().AsList() + }; + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this RangeSelectVectorContext source) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + => SumRange(source.start, source.count, source.vectorSelector, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this RangeSelectVectorContext source) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + => SumRange(source.start, source.count, source.vectorSelector, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this RangeSelectVectorContext source) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + => SumRange(source.start, source.count, source.vectorSelector, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this RangeSelectVectorContext source) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + => SumRange(source.start, source.count, source.vectorSelector, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this RangeSelectVectorContext source) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + => SumRange(source.start, source.count, source.vectorSelector, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this RangeSelectVectorContext source) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + => SumRange(source.start, source.count, source.vectorSelector, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this RangeSelectVectorContext source) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + => SumRange(source.start, source.count, source.vectorSelector, source.selector); + } +} + diff --git a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Projection/Select/SelectVector/SelectVector.ReadOnlySpan.cs similarity index 68% rename from NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Projection/Select/SelectVector/SelectVector.ReadOnlySpan.cs index 0bdbc419a..63532d693 100644 --- a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Projection/Select/SelectVector/SelectVector.ReadOnlySpan.cs @@ -10,24 +10,21 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { - [GeneratorIgnore] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectVectorContext, Vector>, FunctionWrapper> SelectVector(this ReadOnlySpan source, Func, Vector> vectorSelector, Func selector) + static SpanSelectVectorContext, Vector>, FunctionWrapper> SelectVector(this ReadOnlySpan source, Func, Vector> vectorSelector, Func selector) where TSource : struct where TResult : struct => source.SelectVector, Vector>, FunctionWrapper>(new FunctionWrapper, Vector>(vectorSelector), new FunctionWrapper(selector)); - [GeneratorIgnore] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectVectorContext SelectVector(this ReadOnlySpan source, TSelector selector = default) + static SpanSelectVectorContext SelectVector(this ReadOnlySpan source, TSelector selector = default) where TSelector : struct, IFunction, Vector>, IFunction where TSource : struct where TResult : struct => source.SelectVector(selector, selector); - [GeneratorIgnore] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectVectorContext SelectVector(this ReadOnlySpan source, TVectorSelector vectorSelector = default, TSelector selector = default) + static SpanSelectVectorContext SelectVector(this ReadOnlySpan source, TVectorSelector vectorSelector = default, TSelector selector = default) where TVectorSelector : struct, IFunction, Vector> where TSelector : struct, IFunction where TSource : struct @@ -89,8 +86,8 @@ public TResult[] ToArray() => source.ToArrayVector(vectorSelector, selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.ToArrayVector(vectorSelector, selector, pool); + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => source.ToArrayVector(pool, clearOnDispose, vectorSelector, selector); public List ToList() => source.ToListVector(vectorSelector, selector); @@ -103,36 +100,42 @@ public List ToList() where TVectorSelector : struct, IFunction, Vector> where TSelector : struct, IFunction where TSource : struct - => source.source.Sum(source.vectorSelector, source.selector); + => source.source.SumVector(source.vectorSelector, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Sum(this SpanSelectVectorContext source) where TVectorSelector : struct, IFunction, Vector> where TSelector : struct, IFunction where TSource : struct - => source.source.Sum(source.vectorSelector, source.selector); + => source.source.SumVector(source.vectorSelector, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Sum(this SpanSelectVectorContext source) where TVectorSelector : struct, IFunction, Vector> where TSelector : struct, IFunction where TSource : struct - => source.source.Sum(source.vectorSelector, source.selector); + => source.source.SumVector(source.vectorSelector, source.selector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Sum(this SpanSelectVectorContext source) where TVectorSelector : struct, IFunction, Vector> where TSelector : struct, IFunction where TSource : struct - => source.source.Sum(source.vectorSelector, source.selector); - + => source.source.SumVector(source.vectorSelector, source.selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this SpanSelectVectorContext source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction + public static nuint Sum(this SpanSelectVectorContext source) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction where TSource : struct - => source.source.Sum(source.vectorSelector, source.selector); - + => source.source.SumVector(source.vectorSelector, source.selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SpanSelectVectorContext source) + where TVectorSelector : struct, IFunction, Vector> + where TSelector : struct, IFunction + where TSource : struct + => source.source.SumVector(source.vectorSelector, source.selector); } } diff --git a/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ArraySegment.cs b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ArraySegment.cs new file mode 100644 index 000000000..0ff7c776a --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ArraySegment.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static ArraySegmentSelectManyEnumerable> SelectMany(this in ArraySegment source, Func selector) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + => source.SelectMany>(new FunctionWrapper(selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static ArraySegmentSelectManyEnumerable SelectMany(this in ArraySegment source, TSelector selector = default) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(source, selector); + + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct ArraySegmentSelectManyEnumerable + : IValueEnumerable.Enumerator> + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + readonly ArraySegment source; + readonly TSelector selector; + + internal ArraySegmentSelectManyEnumerable(in ArraySegment source, TSelector selector) + => (this.source, this.selector) = (source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + => new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { + readonly TSource[]? source; +#pragma warning disable IDE0044 // Add readonly modifier + TSelector selector; + TSubEnumerator subEnumerator; +#pragma warning restore IDE0044 // Add readonly modifier + readonly int end; + EnumeratorState state; + int sourceIndex; + + internal Enumerator(in ArraySegmentSelectManyEnumerable enumerable) + { + source = enumerable.source.Array; + selector = enumerable.selector; + state = enumerable.source.Count is 0 + ? EnumeratorState.Complete + : EnumeratorState.Enumerating; + sourceIndex = enumerable.source.Offset - 1; + end = sourceIndex + enumerable.source.Count; + subEnumerator = default; + } + + public readonly TResult Current + => subEnumerator.Current; + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => subEnumerator.Current; + + public bool MoveNext() + { + switch (state) + { + case EnumeratorState.Enumerating: + if (++sourceIndex >= end) + { + state = EnumeratorState.Complete; + return false; + } + + var enumerable = selector.Invoke(source![sourceIndex]); + subEnumerator = enumerable.GetEnumerator(); + + state = EnumeratorState.EnumeratingSub; + goto case EnumeratorState.EnumeratingSub; + + case EnumeratorState.EnumeratingSub: + if (!subEnumerator.MoveNext()) + { + state = EnumeratorState.Enumerating; + goto case EnumeratorState.Enumerating; + } + return true; + + default: + return false; + } + } + + [ExcludeFromCodeCoverage] + public readonly void Reset() + => throw new NotSupportedException(); + + public void Dispose() + => subEnumerator.Dispose(); + } + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => this.Count, Enumerator, TResult>(); + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => this.Any, Enumerator, TResult>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any(TPredicate predicate = default) + where TPredicate : struct, IFunction + => this.Any, Enumerator, TResult, TPredicate>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AnyAt(TPredicate predicate = default) + where TPredicate : struct, IFunction + => this.AnyAt, Enumerator, TResult, TPredicate>(predicate); + + #endregion + #region Filtering + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate> WhereAt(TPredicate predicate = default) + where TPredicate : struct, IFunction + => ValueEnumerableExtensions.WhereAt, Enumerator, TResult, TPredicate>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate> Where(TPredicate predicate = default) + where TPredicate : struct, IFunction + => ValueEnumerableExtensions.Where, Enumerator, TResult, TPredicate>(this, predicate); + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, TSelector2> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2, TSelector2>(this, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, TSelector2> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueEnumerableExtensions.SelectAt, Enumerator, TResult, TResult2, TSelector2>(this, selector); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => this.ElementAt, Enumerator, TResult>(index); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => this.First, Enumerator, TResult>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => this.Single, Enumerator, TResult>(); + + #endregion + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ArraySegmentSelectManyEnumerable AsValueEnumerable() + => this; + + public ArraySegmentSelectManyEnumerable AsEnumerable() + => this; + + #endregion + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.SkipEnumerable, Enumerator, TResult> Skip(int count) + => ValueEnumerableExtensions.Skip, Enumerator, TResult>(this, count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.TakeEnumerable, Enumerator, TResult> Take(int count) + => ValueEnumerableExtensions.Take, Enumerator, TResult>(this, count); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, nint, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, nint?, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, nuint, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, nuint?, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this ArraySegmentSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, ArraySegmentSelectManyEnumerable.Enumerator, decimal?, decimal>(); + + } +} + diff --git a/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ReadOnlyMemory.cs b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ReadOnlyMemory.cs new file mode 100644 index 000000000..fa71360ee --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ReadOnlyMemory.cs @@ -0,0 +1,306 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static MemorySelectManyEnumerable> SelectMany(this in ReadOnlyMemory source, Func selector) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + => source.SelectMany>(new FunctionWrapper(selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static MemorySelectManyEnumerable SelectMany(this in ReadOnlyMemory source, TSelector selector = default) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(source, selector); + + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct MemorySelectManyEnumerable + : IValueEnumerable.Enumerator> + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + readonly ReadOnlyMemory source; + readonly TSelector selector; + + internal MemorySelectManyEnumerable(ReadOnlyMemory source, TSelector selector) + => (this.source, this.selector) = (source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + => new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { + readonly ReadOnlyMemory source; +#pragma warning disable IDE0044 // Add readonly modifier + TSelector selector; + TSubEnumerator subEnumerator; +#pragma warning restore IDE0044 // Add readonly modifier + readonly int end; + EnumeratorState state; + int sourceIndex; + + internal Enumerator(in MemorySelectManyEnumerable enumerable) + { + source = enumerable.source; + selector = enumerable.selector; + state = EnumeratorState.Enumerating; + sourceIndex = -1; + end = sourceIndex + enumerable.source.Length; + subEnumerator = default; + } + + public readonly TResult Current + => subEnumerator.Current; + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => subEnumerator.Current; + + public bool MoveNext() + { + switch (state) + { + case EnumeratorState.Enumerating: + if (++sourceIndex >= end) + { + state = EnumeratorState.Complete; + return false; + } + + var enumerable = selector.Invoke(source.Span[sourceIndex]); + subEnumerator = enumerable.GetEnumerator(); + + state = EnumeratorState.EnumeratingSub; + goto case EnumeratorState.EnumeratingSub; + + case EnumeratorState.EnumeratingSub: + if (!subEnumerator.MoveNext()) + { + state = EnumeratorState.Enumerating; + goto case EnumeratorState.Enumerating; + } + return true; + + default: + return false; + } + } + + [ExcludeFromCodeCoverage] + public readonly void Reset() + => throw new NotSupportedException(); + + public void Dispose() + => subEnumerator.Dispose(); + } + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => this.Count, Enumerator, TResult>(); + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => this.Any, Enumerator, TResult>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any(TPredicate predicate = default) + where TPredicate : struct, IFunction + => this.Any, Enumerator, TResult, TPredicate>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AnyAt(TPredicate predicate = default) + where TPredicate : struct, IFunction + => this.AnyAt, Enumerator, TResult, TPredicate>(predicate); + + #endregion + #region Filtering + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate> WhereAt(TPredicate predicate = default) + where TPredicate : struct, IFunction + => ValueEnumerableExtensions.WhereAt, Enumerator, TResult, TPredicate>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate> Where(TPredicate predicate = default) + where TPredicate : struct, IFunction + => ValueEnumerableExtensions.Where, Enumerator, TResult, TPredicate>(this, predicate); + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, TSelector2> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2, TSelector2>(this, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, TSelector2> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueEnumerableExtensions.SelectAt, Enumerator, TResult, TResult2, TSelector2>(this, selector); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => this.ElementAt, Enumerator, TResult>(index); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => this.First, Enumerator, TResult>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => this.Single, Enumerator, TResult>(); + + #endregion + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public MemorySelectManyEnumerable AsValueEnumerable() + => this; + + public MemorySelectManyEnumerable AsEnumerable() + => this; + + #endregion + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.SkipEnumerable, Enumerator, TResult> Skip(int count) + => ValueEnumerableExtensions.Skip, Enumerator, TResult>(this, count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerableExtensions.TakeEnumerable, Enumerator, TResult> Take(int count) + => ValueEnumerableExtensions.Take, Enumerator, TResult>(this, count); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, nint, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, nint?, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, nuint, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, nuint?, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this MemorySelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, MemorySelectManyEnumerable.Enumerator, decimal?, decimal>(); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ReadOnlySpan.cs new file mode 100644 index 000000000..32ba6343b --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ReadOnlySpan.cs @@ -0,0 +1,290 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static SpanSelectManyEnumerable> SelectMany(this ReadOnlySpan source, Func selector) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + => source.SelectMany>(new FunctionWrapper(selector)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static SpanSelectManyEnumerable SelectMany(this ReadOnlySpan source, TSelector selector = default) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(source, selector); + + + [StructLayout(LayoutKind.Auto)] + public readonly ref struct SpanSelectManyEnumerable + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + readonly ReadOnlySpan source; + readonly TSelector selector; + + internal SpanSelectManyEnumerable(ReadOnlySpan source, TSelector selector) + { + this.source = source; + this.selector = selector; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + => new(this); + + [StructLayout(LayoutKind.Auto)] + public ref struct Enumerator + { + readonly ReadOnlySpan source; +#pragma warning disable IDE0044 // Add readonly modifier + TSelector selector; + TSubEnumerator subEnumerator; +#pragma warning restore IDE0044 // Add readonly modifier + readonly int end; + EnumeratorState state; + int sourceIndex; + + internal Enumerator(SpanSelectManyEnumerable enumerable) + { + source = enumerable.source; + selector = enumerable.selector; + state = EnumeratorState.Enumerating; + sourceIndex = -1; + end = sourceIndex + enumerable.source.Length; + subEnumerator = default; + } + + public readonly TResult Current + => subEnumerator.Current; + + public bool MoveNext() + { + switch (state) + { + case EnumeratorState.Enumerating: + if (++sourceIndex >= end) + { + state = EnumeratorState.Complete; + return false; + } + + var enumerable = selector.Invoke(source[sourceIndex]); + subEnumerator = enumerable.GetEnumerator(); + + state = EnumeratorState.EnumeratingSub; + goto case EnumeratorState.EnumeratingSub; + + case EnumeratorState.EnumeratingSub: + if (!subEnumerator.MoveNext()) + { + state = EnumeratorState.Enumerating; + goto case EnumeratorState.Enumerating; + } + return true; + + default: + return false; + } + } + + [ExcludeFromCodeCoverage] + public readonly void Reset() + => throw new NotSupportedException(); + + public void Dispose() + => subEnumerator.Dispose(); + } +/* + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly int Count() + => this.Count, Enumerator, TResult>(); + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => this.Any, Enumerator, TResult>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any(Func predicate) + => this.Any, Enumerator, TResult>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any(TPredicate predicate = default) + where TPredicate : struct, IFunction + => this.Any, Enumerator, TResult, TPredicate>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any(Func predicate) + => this.Any, Enumerator, TResult>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AnyAt(TPredicate predicate = default) + where TPredicate : struct, IFunction + => this.AnyAt, Enumerator, TResult, TPredicate>(predicate); + + #endregion + #region Filtering + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, FunctionWrapper> Where(Func predicate) + => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate> WhereAt(TPredicate predicate = default) + where TPredicate : struct, IFunction + => ValueEnumerableExtensions.WhereAt, Enumerator, TResult, TPredicate>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, FunctionWrapper> Where(System.Func predicate) + => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate> Where(TPredicate predicate = default) + where TPredicate : struct, IFunction + => ValueEnumerableExtensions.Where, Enumerator, TResult, TPredicate>(this, predicate); + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) + => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2>(this, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, TSelector2> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2, TSelector2>(this, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) + => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2>(this, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, TSelector2> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueEnumerableExtensions.SelectAt, Enumerator, TResult, TResult2, TSelector2>(this, selector); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => this.ElementAt, Enumerator, TResult>(index); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => this.First, Enumerator, TResult>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => this.Single, Enumerator, TResult>(); + + #endregion + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.AsyncValueEnumerableWrapper, Enumerator, TResult> AsAsyncValueEnumerable() + => ValueEnumerableExtensions.AsAsyncValueEnumerable, Enumerator, TResult>(this); + + #endregion + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.SkipEnumerable, Enumerator, TResult> Skip(int count) + => ValueEnumerableExtensions.Skip, Enumerator, TResult>(this, count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ValueEnumerableExtensions.TakeEnumerable, Enumerator, TResult> Take(int count) + => ValueEnumerableExtensions.Take, Enumerator, TResult>(this, count); + + #endregion +*/ + } + /* + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SpanSelectManyEnumerable source) + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SpanSelectManyEnumerable.Enumerator, decimal?, decimal>(); +*/ + } +} + diff --git a/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ValueEnumerable.cs new file mode 100644 index 000000000..b07960280 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ValueEnumerable.cs @@ -0,0 +1,328 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueEnumerableExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SelectManyEnumerable SelectMany(this TEnumerable source, TSelector selector = default) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => new(source, selector); + + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct SelectManyEnumerable + : IValueEnumerable.Enumerator> + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + readonly TEnumerable source; + readonly TSelector selector; + + internal SelectManyEnumerable(in TEnumerable source, TSelector selector) + => (this.source, this.selector) = (source, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + => new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator sourceEnumerator; + TSelector selector; + TSubEnumerator subEnumerator; +#pragma warning restore IDE0044 // Add readonly modifier + int state; + + internal Enumerator(in SelectManyEnumerable enumerable) + { + sourceEnumerator = enumerable.source.GetEnumerator(); + selector = enumerable.selector; + subEnumerator = default; + state = 0; + } + + public readonly TResult Current + => subEnumerator.Current; + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => subEnumerator.Current; + + public bool MoveNext() + { + switch (state) + { + case 0: + state = 1; + goto case 1; + + case 1: + if (!sourceEnumerator.MoveNext()) + break; + + var enumerable = selector.Invoke(sourceEnumerator.Current); + subEnumerator = enumerable.GetEnumerator(); + + state = 2; + goto case 2; + + case 2: + if (!subEnumerator.MoveNext()) + { + state = 1; + goto case 1; + } + return true; + } + return false; + } + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public void Dispose() + => subEnumerator.Dispose(); + } + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => this.Count, Enumerator, TResult>(); + + #endregion + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => this.Any, Enumerator, TResult>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any(TPredicate predicate = default) + where TPredicate : struct, IFunction + => this.Any, Enumerator, TResult, TPredicate>(predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AnyAt(TPredicate predicate = default) + where TPredicate : struct, IFunction + => this.AnyAt, Enumerator, TResult, TPredicate>(predicate); + + #endregion + #region Filtering + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public WhereAtEnumerable, Enumerator, TResult, TPredicate> WhereAt(TPredicate predicate = default) + where TPredicate : struct, IFunction + => ValueEnumerableExtensions.WhereAt, Enumerator, TResult, TPredicate>(this, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public WhereEnumerable, Enumerator, TResult, TPredicate> Where(TPredicate predicate = default) + where TPredicate : struct, IFunction + => ValueEnumerableExtensions.Where, Enumerator, TResult, TPredicate>(this, predicate); + + #endregion + #region Projection + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectEnumerable, Enumerator, TResult, TResult2, TSelector2> Select(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2, TSelector2>(this, selector); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectAtEnumerable, Enumerator, TResult, TResult2, TSelector2> SelectAt(TSelector2 selector = default) + where TSelector2 : struct, IFunction + => ValueEnumerableExtensions.SelectAt, Enumerator, TResult, TResult2, TSelector2>(this, selector); + + #endregion + #region Element + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option ElementAt(int index) + => this.ElementAt, Enumerator, TResult>(index); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option First() + => this.First, Enumerator, TResult>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Option Single() + => this.Single, Enumerator, TResult>(); + + #endregion + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SelectManyEnumerable AsValueEnumerable() + => this; + + public SelectManyEnumerable AsEnumerable() + => this; + + #endregion + #region Partitioning + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipEnumerable, Enumerator, TResult> Skip(int count) + => ValueEnumerableExtensions.Skip, Enumerator, TResult>(this, count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TakeEnumerable, Enumerator, TResult> Take(int count) + => ValueEnumerableExtensions.Take, Enumerator, TResult>(this, count); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, nint, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, nint?, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, nuint, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, nuint?, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SelectManyEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => source.Sum, SelectManyEnumerable.Enumerator, decimal?, decimal>(); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ValueReadOnlyCollection.cs new file mode 100644 index 000000000..b171a53c8 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ValueReadOnlyCollection.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadonlyCollectionExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueEnumerableExtensions.SelectManyEnumerable SelectMany(this TEnumerable source, TSelector selector = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueEnumerableExtensions.SelectMany(source, selector); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ValueReadOnlyList.cs new file mode 100644 index 000000000..2425f25bb --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Projection/SelectMany/SelectMany/SelectMany.ValueReadOnlyList.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadonlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueEnumerableExtensions.SelectManyEnumerable SelectMany(this TEnumerable source, TSelector selector = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TSubEnumerable : IValueEnumerable + where TSubEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + => ValueEnumerableExtensions.SelectMany(source, selector); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Properties/AssemblyInfo.cs b/NetFabric.Hyperlinq.Core/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..c1bd8a3cf --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly:InternalsVisibleTo("NetFabric.Hyperlinq.Core.UnitTests")] \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Quantifier/All/All.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Quantifier/All/All.ReadOnlySpan.cs similarity index 68% rename from NetFabric.Hyperlinq/Quantifier/All/All.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Quantifier/All/All.ReadOnlySpan.cs index 251e67edd..43c95684c 100644 --- a/NetFabric.Hyperlinq/Quantifier/All/All.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/All/All.ReadOnlySpan.cs @@ -6,10 +6,10 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this ReadOnlySpan source, Func predicate) + static bool All(this ReadOnlySpan source, Func predicate) => source.All(new FunctionWrapper(predicate)); - - public static bool All(this ReadOnlySpan source, TPredicate predicate = default) + + static bool All(this ReadOnlySpan source, TPredicate predicate = default) where TPredicate : struct, IFunction { foreach (var item in source) @@ -21,10 +21,10 @@ public static bool All(this ReadOnlySpan source, Func(this ReadOnlySpan source, Func predicate) + static bool All(this ReadOnlySpan source, Func predicate) => source.AllAt(new FunctionWrapper(predicate)); - - public static bool AllAt(this ReadOnlySpan source, TPredicate predicate = default) + + static bool AllAt(this ReadOnlySpan source, TPredicate predicate = default) where TPredicate : struct, IFunction { for (var index = 0; index < source.Length; index++) diff --git a/NetFabric.Hyperlinq/Quantifier/All/All.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Quantifier/All/All.ValueEnumerable.cs similarity index 61% rename from NetFabric.Hyperlinq/Quantifier/All/All.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Quantifier/All/All.ValueEnumerable.cs index a43bc4eeb..356f3c912 100644 --- a/NetFabric.Hyperlinq/Quantifier/All/All.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/All/All.ValueEnumerable.cs @@ -7,12 +7,6 @@ namespace NetFabric.Hyperlinq public static partial class ValueEnumerableExtensions { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this TEnumerable source, Func predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source.All>(new FunctionWrapper(predicate)); - public static bool All(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -26,13 +20,6 @@ public static partial class ValueEnumerableExtensions } return true; } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this TEnumerable source, Func predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source.AllAt>(new FunctionWrapper(predicate)); public static bool AllAt(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueEnumerable diff --git a/NetFabric.Hyperlinq/Quantifier/All/All.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Quantifier/All/All.ValueReadOnlyCollection.cs similarity index 57% rename from NetFabric.Hyperlinq/Quantifier/All/All.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Quantifier/All/All.ValueReadOnlyCollection.cs index 7eb86823a..b1abcc6b7 100644 --- a/NetFabric.Hyperlinq/Quantifier/All/All.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/All/All.ValueReadOnlyCollection.cs @@ -6,12 +6,6 @@ namespace NetFabric.Hyperlinq { public static partial class ValueReadOnlyCollectionExtensions { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this TEnumerable source, Func predicate) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => All>(source, new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool All(this TEnumerable source, TPredicate predicate = default) @@ -19,12 +13,6 @@ public static partial class ValueReadOnlyCollectionExtensions where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction => source.Count is 0 || ValueEnumerableExtensions.All(source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this TEnumerable source, Func predicate) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => AllAt>(source, new FunctionWrapper(predicate)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool AllAt(this TEnumerable source, TPredicate predicate = default) diff --git a/NetFabric.Hyperlinq.Core/Quantifier/All/All.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Quantifier/All/All.ValueReadOnlyList.cs new file mode 100644 index 000000000..d94386393 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Quantifier/All/All.ValueReadOnlyList.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool All(this TEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.All(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllAt(this TEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.AllAt(source, predicate); + } +} + diff --git a/NetFabric.Hyperlinq/Quantifier/All/AllAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Quantifier/All/AllAsync.AsyncValueEnumerable.cs similarity index 100% rename from NetFabric.Hyperlinq/Quantifier/All/AllAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Quantifier/All/AllAsync.AsyncValueEnumerable.cs diff --git a/NetFabric.Hyperlinq/Quantifier/Any/Any.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ReadOnlySpan.cs similarity index 66% rename from NetFabric.Hyperlinq/Quantifier/Any/Any.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ReadOnlySpan.cs index cd23a9106..f32ae561c 100644 --- a/NetFabric.Hyperlinq/Quantifier/Any/Any.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ReadOnlySpan.cs @@ -5,17 +5,17 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this ReadOnlySpan source) + static bool Any(this ReadOnlySpan source) => source.Length is not 0; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this in ReadOnlySpan source, Func predicate) + static bool Any(this in ReadOnlySpan source, Func predicate) => source.Any(new FunctionWrapper(predicate)); - - public static bool Any(this ReadOnlySpan source, TPredicate predicate = default) + + static bool Any(this ReadOnlySpan source, TPredicate predicate = default) where TPredicate : struct, IFunction { foreach (var item in source) @@ -27,10 +27,10 @@ public static bool Any(this in ReadOnlySpan source, Func(this in ReadOnlySpan source, Func predicate) + static bool Any(this in ReadOnlySpan source, Func predicate) => source.AnyAt(new FunctionWrapper(predicate)); - public static bool AnyAt(this ReadOnlySpan source, TPredicate predicate = default) + static bool AnyAt(this ReadOnlySpan source, TPredicate predicate = default) where TPredicate : struct, IFunction { for (var index = 0; index < source.Length; index++) diff --git a/NetFabric.Hyperlinq/Quantifier/Any/Any.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ValueEnumerable.cs similarity index 66% rename from NetFabric.Hyperlinq/Quantifier/Any/Any.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ValueEnumerable.cs index 6cfd4c202..985603f09 100644 --- a/NetFabric.Hyperlinq/Quantifier/Any/Any.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ValueEnumerable.cs @@ -15,12 +15,6 @@ public static partial class ValueEnumerableExtensions return enumerator.MoveNext(); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TEnumerable source, Func predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source.Any>(new FunctionWrapper(predicate)); - public static bool Any(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator @@ -35,12 +29,6 @@ public static partial class ValueEnumerableExtensions return false; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TEnumerable source, Func predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source.AnyAt>(new FunctionWrapper(predicate)); - public static bool AnyAt(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ValueReadOnlyCollection.cs similarity index 78% rename from NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ValueReadOnlyCollection.cs index 49d4c1145..5dad306eb 100644 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ValueReadOnlyCollection.cs @@ -14,17 +14,18 @@ public static partial class ValueReadOnlyCollectionExtensions => source.Count is not 0; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TEnumerable source, Func predicate) + public static bool Any(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator - => Any>(source, new FunctionWrapper(predicate)); + where TPredicate : struct, IFunction + => source.Count is not 0 && ValueEnumerableExtensions.Any(source, predicate); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TEnumerable source, TPredicate predicate = default) + public static bool AnyAt(this TEnumerable source, TPredicate predicate = default) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => source.Count is not 0 && ValueEnumerableExtensions.Any(source, predicate); + where TPredicate : struct, IFunction + => source.Count is not 0 && ValueEnumerableExtensions.AnyAt(source, predicate); } } diff --git a/NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ValueReadOnlyList.cs new file mode 100644 index 000000000..d2df510ab --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Quantifier/Any/Any.ValueReadOnlyList.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(this TEnumerable source) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.Any(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(this TEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.Any(source, predicate); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyAt(this TEnumerable source, TPredicate predicate = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + where TPredicate : struct, IFunction + => ValueReadOnlyCollectionExtensions.AnyAt(source, predicate); + } +} + diff --git a/NetFabric.Hyperlinq/Quantifier/Any/AnyAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Quantifier/Any/AnyAsync.AsyncValueEnumerable.cs similarity index 100% rename from NetFabric.Hyperlinq/Quantifier/Any/AnyAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Quantifier/Any/AnyAsync.AsyncValueEnumerable.cs diff --git a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.Enumerable.cs b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.Enumerable.cs similarity index 80% rename from NetFabric.Hyperlinq/Quantifier/Contains/Contains.Enumerable.cs rename to NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.Enumerable.cs index 20cbf1744..052400a66 100644 --- a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.Enumerable.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.Enumerable.cs @@ -1,15 +1,14 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; +using System.Collections.Generic; namespace NetFabric.Hyperlinq { public static partial class EnumerableExtensions { + internal static bool Contains(this TEnumerable source, TSource value, IEqualityComparer? comparer = default) where TEnumerable : IEnumerable { - if (comparer is null || ReferenceEquals(comparer, EqualityComparer.Default)) + if (comparer.UseDefaultComparer()) { // ReSharper disable once HeapView.PossibleBoxingAllocation if (source is ICollection collection) @@ -45,22 +44,22 @@ static bool ComparerContains(TEnumerable source, TSource value, IEqualityCompare } } + internal static bool Contains(this TEnumerable source, TEnumeratorGenerator getEnumerator, TSource value, IEqualityComparer? comparer = default) where TEnumerable : IEnumerable where TEnumerator : struct, IEnumerator where TEnumeratorGenerator : struct, IFunction { - // TODO: - //if (comparer is null || ReferenceEquals(comparer, EqualityComparer.Default)) - //{ - // if (source is ICollection collection) - // return collection.Contains(value); - - // if (Utils.IsValueType()) - // return DefaultContains(source, value, getEnumerator); - //} + if (comparer.UseDefaultComparer()) + { + return source switch + { + // ReSharper disable once HeapView.PossibleBoxingAllocation + ICollection collection => collection.Contains(value), + _ => DefaultContains(source, value, getEnumerator), + }; + } - comparer ??= EqualityComparer.Default; return ComparerContains(source, value, comparer, getEnumerator); static bool DefaultContains(TEnumerable source, TSource value, TEnumeratorGenerator getEnumerator) @@ -74,8 +73,9 @@ static bool DefaultContains(TEnumerable source, TSource value, TEnumeratorGenera return false; } - static bool ComparerContains(TEnumerable source, TSource value, IEqualityComparer comparer, TEnumeratorGenerator getEnumerator) + static bool ComparerContains(TEnumerable source, TSource value, IEqualityComparer? comparer, TEnumeratorGenerator getEnumerator) { + comparer ??= EqualityComparer.Default; using var enumerator = getEnumerator.Invoke(source); while (enumerator.MoveNext()) { diff --git a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ReadOnlySpan.cs similarity index 55% rename from NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ReadOnlySpan.cs index 6655f44fd..67fcb78d4 100644 --- a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ReadOnlySpan.cs @@ -5,12 +5,12 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - public static bool Contains(this ReadOnlySpan source, TSource value, IEqualityComparer? comparer = default) + static bool Contains(this ReadOnlySpan source, TSource value, IEqualityComparer? comparer = default) { return source switch { { Length: 0 } => false, - _ => Utils.UseDefault(comparer) + _ => comparer.UseDefaultComparer() ? ValueContains(source, value) : ReferenceContains(source, value, comparer) }; @@ -37,13 +37,14 @@ static bool ReferenceContains(ReadOnlySpan source, TSource value, IEqua } } + static bool Contains(this ReadOnlySpan source, TResult value, IEqualityComparer? comparer, TSelector selector) where TSelector : struct, IFunction { return source switch { { Length: 0 } => false, - _ => Utils.UseDefault(comparer) + _ => comparer.UseDefaultComparer() ? ValueContains(source, value, selector) : ReferenceContains(source, value, comparer, selector) }; @@ -70,39 +71,6 @@ static bool ReferenceContains(ReadOnlySpan source, TResult value, IEqua } } - static bool ContainsRef(this ReadOnlySpan source, TResult value, IEqualityComparer? comparer, TSelector selector) - where TSelector : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => false, - _ => Utils.UseDefault(comparer) - ? ValueContains(source, value, selector) - : ReferenceContains(source, value, comparer, selector) - }; - - static bool ValueContains(ReadOnlySpan source, TResult value, TSelector selector) - { - foreach (ref readonly var item in source) - { - if (EqualityComparer.Default.Equals(selector.Invoke(in item), value)) - return true; - } - return false; - } - - static bool ReferenceContains(ReadOnlySpan source, TResult value, IEqualityComparer? comparer, TSelector selector) - { - comparer ??= EqualityComparer.Default; - foreach (ref readonly var item in source) - { - if (comparer.Equals(selector.Invoke(in item), value)) - return true; - } - return false; - } - } - static bool ContainsAt(this ReadOnlySpan source, TResult value, IEqualityComparer? comparer, TSelector selector) where TSelector : struct, IFunction @@ -136,39 +104,6 @@ static bool ReferenceContains(ReadOnlySpan source, TResult value, IEqua return false; } } - - static bool ContainsAtRef(this ReadOnlySpan source, TResult value, IEqualityComparer? comparer, TSelector selector) - where TSelector : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => false, - _ => Utils.IsValueType() - ? ValueContains(source, value, selector) - : ReferenceContains(source, value, comparer, selector), - }; - - static bool ValueContains(ReadOnlySpan source, TResult value, TSelector selector) - { - for (var index = 0; index < source.Length; index++) - { - if (EqualityComparer.Default.Equals(selector.Invoke(in source[index], index), value)) - return true; - } - return false; - } - - static bool ReferenceContains(ReadOnlySpan source, TResult value, IEqualityComparer? comparer, TSelector selector) - { - comparer ??= EqualityComparer.Default; - for (var index = 0; index < source.Length; index++) - { - if (comparer.Equals(selector.Invoke(in source[index], index), value)) - return true; - } - return false; - } - } } } diff --git a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ValueEnumerable.cs similarity index 73% rename from NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ValueEnumerable.cs index c2954c2ca..0540ec1b5 100644 --- a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ValueEnumerable.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; namespace NetFabric.Hyperlinq { @@ -9,8 +8,9 @@ public static partial class ValueEnumerableExtensions where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator { - if (comparer is null || ReferenceEquals(comparer, EqualityComparer.Default)) + if (comparer.UseDefaultComparer()) { + // ReSharper disable once HeapView.PossibleBoxingAllocation if (source is ICollection collection) return collection.Contains(value); @@ -34,7 +34,6 @@ static bool DefaultContains(TEnumerable source, TSource value) static bool ComparerContains(TEnumerable source, TSource value, IEqualityComparer? comparer) { comparer ??= EqualityComparer.Default; - using var enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { @@ -46,12 +45,13 @@ static bool ComparerContains(TEnumerable source, TSource value, IEqualityCompare } + internal static bool Contains(this TEnumerable source, TResult value, IEqualityComparer? comparer, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction { - return Utils.UseDefault(comparer) + return comparer.UseDefaultComparer() ? ValueContains(source, value, selector) : ReferenceContains(source, value, comparer, selector); @@ -80,39 +80,6 @@ static bool ReferenceContains(TEnumerable source, TResult value, IEqualityCompar } } - internal static bool ContainsRef(this TEnumerable source, TResult value, IEqualityComparer? comparer, TSelector selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunctionIn - { - return Utils.IsValueType() - ? ValueContains(source, value, selector) - : ReferenceContains(source, value, comparer, selector); - - static bool ValueContains(TEnumerable source, TResult value, TSelector selector) - { - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - { - if (EqualityComparer.Default.Equals(selector.Invoke(enumerator.Current), value)) - return true; - } - return false; - } - - static bool ReferenceContains(TEnumerable source, TResult value, IEqualityComparer? comparer, TSelector selector) - { - comparer ??= EqualityComparer.Default; - - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - { - if (comparer.Equals(selector.Invoke(enumerator.Current), value)) - return true; - } - return false; - } - } internal static bool ContainsAt(this TEnumerable source, TResult value, IEqualityComparer? comparer, TSelector selector) where TEnumerable : IValueEnumerable diff --git a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ValueReadOnlyCollection.cs similarity index 88% rename from NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ValueReadOnlyCollection.cs index f44787d7b..4c4e1e62e 100644 --- a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ValueReadOnlyCollection.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq @@ -12,6 +11,7 @@ public static partial class ValueReadOnlyCollectionExtensions where TEnumerator : struct, IEnumerator => source.Count is not 0 && ValueEnumerableExtensions.Contains(source, value, comparer); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool Contains(this TEnumerable source, TResult value, IEqualityComparer? comparer, TSelector selector) where TEnumerable : IValueReadOnlyCollection @@ -19,8 +19,9 @@ public static partial class ValueReadOnlyCollectionExtensions where TSelector : struct, IFunction => source.Count is not 0 && ValueEnumerableExtensions.Contains(source, value, comparer, selector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool ContainsAt(this TEnumerable source, TResult value, IEqualityComparer? comparer, TSelector selector) + internal static bool ContainsAt(this TEnumerable source, TResult value, IEqualityComparer? comparer, TSelector selector) where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction diff --git a/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ValueReadOnlyList.cs new file mode 100644 index 000000000..fd94cdc4d --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Quantifier/Contains/Contains.ValueReadOnlyList.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Contains(this TEnumerable source, TSource value, IEqualityComparer? comparer = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.Contains(source, value, comparer); + } +} diff --git a/NetFabric.Hyperlinq/Quantifier/Contains/ContainsAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Quantifier/Contains/ContainsAsync.AsyncValueEnumerable.cs similarity index 76% rename from NetFabric.Hyperlinq/Quantifier/Contains/ContainsAsync.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Quantifier/Contains/ContainsAsync.AsyncValueEnumerable.cs index 48f146f26..be0b66670 100644 --- a/NetFabric.Hyperlinq/Quantifier/Contains/ContainsAsync.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/Contains/ContainsAsync.AsyncValueEnumerable.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; @@ -12,7 +11,7 @@ public static partial class AsyncValueEnumerableExtensions where TEnumerator : struct, IAsyncEnumerator { var enumerator = source.GetAsyncEnumerator(); - await using (enumerator.ConfigureAwait(false)) + try { while (await enumerator.MoveNextAsync().ConfigureAwait(false)) { @@ -20,22 +19,25 @@ await using (enumerator.ConfigureAwait(false)) return true; } } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } return false; } - public static ValueTask ContainsAsync(this TEnumerable source, TSource value, IEqualityComparer? comparer = default, CancellationToken cancellationToken = default) + public static ValueTask ContainsAsync(this TEnumerable source, TSource value, IEqualityComparer? comparer, CancellationToken cancellationToken = default) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator { - if (Utils.UseDefault(comparer)) - return DefaultContainsAsync(source, value, cancellationToken); - - return ComparerContainsAsync(source, value, comparer, cancellationToken); + return comparer.UseDefaultComparer() + ? DefaultContainsAsync(source, value, cancellationToken) + : ComparerContainsAsync(source, value, comparer, cancellationToken); static async ValueTask DefaultContainsAsync(TEnumerable source, TSource value, CancellationToken cancellationToken) { var enumerator = source.GetAsyncEnumerator(cancellationToken); - await using (enumerator.ConfigureAwait(false)) + try { while (await enumerator.MoveNextAsync().ConfigureAwait(false)) { @@ -43,6 +45,10 @@ await using (enumerator.ConfigureAwait(false)) return true; } } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } return false; } @@ -50,7 +56,7 @@ static async ValueTask ComparerContainsAsync(TEnumerable source, TSource v { comparer ??= EqualityComparer.Default; var enumerator = source.GetAsyncEnumerator(cancellationToken); - await using (enumerator.ConfigureAwait(false)) + try { while (await enumerator.MoveNextAsync().ConfigureAwait(false)) { @@ -58,6 +64,10 @@ await using (enumerator.ConfigureAwait(false)) return true; } } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } return false; } } diff --git a/NetFabric.Hyperlinq/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.cs similarity index 58% rename from NetFabric.Hyperlinq/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.cs index 55fab417e..11c7e6beb 100644 --- a/NetFabric.Hyperlinq/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/ContainsVector/ContainsVector.ReadOnlySpan.cs @@ -6,10 +6,10 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - public static bool ContainsVector(this ReadOnlySpan source, TSource value) + static bool ContainsVector(this ReadOnlySpan source, TSource value) where TSource : struct { - if (source.Length is 0) + if (source.IsEmpty) return false; if (Vector.IsHardwareAccelerated && source.Length > Vector.Count * 2) @@ -23,32 +23,25 @@ public static bool ContainsVector(this ReadOnlySpan source, TS return true; } - for (var index = source.Length - (source.Length % Vector.Count); index < source.Length; index++) - { - var item = source[index]; - if (GenericsOperator.Equals(item, value)) - return true; - } + var count = source.Length % Vector.Count; + source = source.Slice(source.Length - count, count); } - else + foreach (var item in source) { - foreach (var item in source) - { - if (GenericsOperator.Equals(item, value)) - return true; - } - } - + if (Scalar.Equals(item, value)) + return true; + } return false; } + static bool ContainsVector(this ReadOnlySpan source, TResult value, TVectorSelector vectorSelector, TSelector selector) where TVectorSelector : struct, IFunction, Vector> where TSelector : struct, IFunction where TSource : struct where TResult : struct { - if (source.Length is 0) + if (source.IsEmpty) return false; if (Vector.IsHardwareAccelerated && source.Length > Vector.Count * 2) @@ -62,22 +55,14 @@ public static bool ContainsVector(this ReadOnlySpan source, TS return true; } - for (var index = source.Length - (source.Length % Vector.Count); index < source.Length; index++) - { - var item = source[index]; - if (GenericsOperator.Equals(selector.Invoke(item), value)) - return true; - } + var count = source.Length % Vector.Count; + source = source.Slice(source.Length - count, count); } - else + foreach (var item in source) { - foreach (var item in source) - { - if (GenericsOperator.Equals(selector.Invoke(item), value)) - return true; - } + if (Scalar.Equals(selector.Invoke(item), value)) + return true; } - return false; } } diff --git a/NetFabric.Hyperlinq/Quantifier/ContainsVector/ContainsVector.Span.cs b/NetFabric.Hyperlinq.Core/Quantifier/ContainsVector/ContainsVector.Span.cs similarity index 60% rename from NetFabric.Hyperlinq/Quantifier/ContainsVector/ContainsVector.Span.cs rename to NetFabric.Hyperlinq.Core/Quantifier/ContainsVector/ContainsVector.Span.cs index deda3cf86..0bfe618fe 100644 --- a/NetFabric.Hyperlinq/Quantifier/ContainsVector/ContainsVector.Span.cs +++ b/NetFabric.Hyperlinq.Core/Quantifier/ContainsVector/ContainsVector.Span.cs @@ -7,9 +7,9 @@ public static partial class ArrayExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool ContainsVector(this Span source, TSource value) + static bool ContainsVector(this Span source, TSource value) where TSource : struct - => ((ReadOnlySpan)source).ContainsVector(value); + => source.AsReadOnlySpan().ContainsVector(value); } } diff --git a/NetFabric.Hyperlinq.Core/Resource.Designer.cs b/NetFabric.Hyperlinq.Core/Resource.Designer.cs new file mode 100644 index 000000000..ff4ee5dc4 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Resource.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace NetFabric.Hyperlinq { + using System; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resource { + + private static System.Resources.ResourceManager resourceMan; + + private static System.Globalization.CultureInfo resourceCulture; + + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resource() { + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Resources.ResourceManager ResourceManager { + get { + if (object.Equals(null, resourceMan)) { + System.Resources.ResourceManager temp = new System.Resources.ResourceManager("NetFabric.Hyperlinq.Resource", typeof(Resource).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static string ArraySegmentNull { + get { + return ResourceManager.GetString("ArraySegmentNull", resourceCulture); + } + } + + internal static string DestinationNotLongEnough { + get { + return ResourceManager.GetString("DestinationNotLongEnough", resourceCulture); + } + } + + internal static string EmptySequence { + get { + return ResourceManager.GetString("EmptySequence", resourceCulture); + } + } + + internal static string NotSingleSequence { + get { + return ResourceManager.GetString("NotSingleSequence", resourceCulture); + } + } + } +} diff --git a/NetFabric.Hyperlinq.Core/Resource.resx b/NetFabric.Hyperlinq.Core/Resource.resx new file mode 100644 index 000000000..05b1efb3f --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Resource.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The array in the ArraySegment is null + + + Destination array was not long enough. Check the destination index, length, and the array's lower bounds. + + + Sequence contains no elements + + + Sequence contains more than one element + + \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ArraySegment.cs b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ArraySegment.cs similarity index 74% rename from NetFabric.Hyperlinq/Set/Distinct/Distinct.ArraySegment.cs rename to NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ArraySegment.cs index 26738634b..ffbe3f74b 100644 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ArraySegment.cs +++ b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ArraySegment.cs @@ -11,7 +11,7 @@ namespace NetFabric.Hyperlinq public static partial class ArrayExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentDistinctEnumerable Distinct(this in ArraySegment source, IEqualityComparer? comparer = default) + static ArraySegmentDistinctEnumerable Distinct(this in ArraySegment source, IEqualityComparer? comparer = default) => new(source, comparer); [StructLayout(LayoutKind.Auto)] @@ -25,12 +25,14 @@ internal ArraySegmentDistinctEnumerable(in ArraySegment source, IEquali => (this.source, this.comparer) = (source, comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -65,10 +67,14 @@ internal Enumerator(in ArraySegmentDistinctEnumerable enumerable) [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { + var index = this.index; while (++index <= end) { if (set.Add(source![index])) + { + this.index = index; return true; + } } return false; } @@ -81,7 +87,7 @@ public void Dispose() => set.Dispose(); } - readonly Set GetSet() + Set GetSet() { var set = new Set(comparer); foreach (var item in source.AsSpan()) @@ -89,20 +95,38 @@ public void Dispose() return set; } + #region Aggregation + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() + public int Count() => source switch { { Count: 0 } => 0, _ => GetSet().Count }; + + #endregion + + #region Quantifier [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any() - => source is not 0; + public bool Any() + => source.Count is not 0; + + #endregion + + #region Conversion [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly TSource[] ToArray() + public ArraySegmentDistinctEnumerable AsValueEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ArraySegmentDistinctEnumerable AsEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TSource[] ToArray() => source switch { { Count: 0 } => Array.Empty(), @@ -110,21 +134,19 @@ public void Dispose() }; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly IMemoryOwner ToArray(MemoryPool pool) - => source switch - { - { Count: 0 } => pool.Rent(0), - _ => GetSet().ToArray(pool) - }; + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => GetSet().ToArray(pool, clearOnDispose); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly List ToList() + public List ToList() => source switch { // ReSharper disable once HeapView.ObjectAllocation.Evident { Count: 0 } => new List(), _ => GetSet().ToList() }; + + #endregion } } } diff --git a/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.AsyncValueEnumerable.cs new file mode 100644 index 000000000..0c07e13c3 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.AsyncValueEnumerable.cs @@ -0,0 +1,320 @@ +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class AsyncValueEnumerableExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static DistinctEnumerable Distinct( + this TEnumerable source, + IEqualityComparer? comparer = default) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => new(source, comparer); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct DistinctEnumerable + : IAsyncValueEnumerable.Enumerator> + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + { + readonly TEnumerable source; + readonly IEqualityComparer? comparer; + + internal DistinctEnumerable(TEnumerable source, IEqualityComparer? comparer) + => (this.source, this.comparer) = (source, comparer); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + => new(in this, cancellationToken); + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this, cancellationToken); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IAsyncEnumerator + , IAsyncStateMachine + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; +#pragma warning restore IDE0044 // Add readonly modifier + readonly IEqualityComparer? comparer; + Set set; + + int state; + AsyncValueTaskMethodBuilder builder; +#pragma warning disable IDE1006 // Naming Styles + bool s__1; +#pragma warning restore IDE1006 // Naming Styles + ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; + ValueTaskAwaiter u__2; + + internal Enumerator(in DistinctEnumerable enumerable, CancellationToken cancellationToken) + { + enumerator = enumerable.source.GetAsyncEnumerator(cancellationToken); + comparer = enumerable.comparer; + set = new Set(comparer); + + state = default; + builder = default; + s__1 = default; + u__1 = default; + u__2 = default; + } + + public readonly TSource Current + => enumerator.Current; + readonly TSource IAsyncEnumerator.Current + => enumerator.Current; + + //public async ValueTask MoveNextAsync() + //{ + // while (await enumerator.MoveNextAsync().ConfigureAwait(false)) + // { + // if (set.Add(enumerator.Current)) + // return true; + // } + + // await DisposeAsync(); + // return false; + //} + + public ValueTask MoveNextAsync() + { + state = -1; + builder = AsyncValueTaskMethodBuilder.Create(); + builder.Start(ref this); + return builder.Task; + } + + public ValueTask DisposeAsync() + { + set.Dispose(); + return enumerator.DisposeAsync(); + } + + void IAsyncStateMachine.MoveNext() + { + var num = state; + bool result; + try + { + ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter awaiter; + if (num is 0) + { + awaiter = u__1; + u__1 = default; + num = state = -1; + goto IL_00c0; + } + if (num != 1) + { + goto IL_004c; + } + var awaiter2 = u__2; + u__2 = default; + num = state = -1; + goto IL_013c; + IL_00c0: + s__1 = awaiter.GetResult(); + if (!s__1) + { + awaiter2 = DisposeAsync().GetAwaiter(); + if (!awaiter2.IsCompleted) + { + num = state = 1; + u__2 = awaiter2; + builder.AwaitUnsafeOnCompleted(ref awaiter2, ref this); + return; + } + goto IL_013c; + } + if (!set.Add(enumerator.Current)) + { + goto IL_004c; + } + result = true; + goto end_IL_0007; + IL_004c: + awaiter = enumerator.MoveNextAsync().ConfigureAwait(false).GetAwaiter(); + if (!awaiter.IsCompleted) + { + num = state = 0; + u__1 = awaiter; + builder.AwaitUnsafeOnCompleted(ref awaiter, ref this); + return; + } + goto IL_00c0; + IL_013c: + awaiter2.GetResult(); + result = false; + end_IL_0007: + ; + } + catch (Exception exception) + { + state = -2; + builder.SetException(exception); + return; + } + state = -2; + builder.SetResult(result); + } + + void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) + { } + } + + async ValueTask> FillSetAsync(CancellationToken cancellationToken) + { + var set = new Set(comparer); + var enumerator = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await enumerator.MoveNextAsync().ConfigureAwait(false)) + _ = set.Add(enumerator.Current); + } + finally + { + await enumerator.DisposeAsync().ConfigureAwait(false); + } + return set; + } + + #region Aggregation + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public async ValueTask CountAsync(CancellationToken cancellationToken = default) + => (await FillSetAsync(cancellationToken).ConfigureAwait(false)).Count; + + #endregion + + #region Quantifier + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueTask AnyAsync(CancellationToken cancellationToken = default) + => source.AnyAsync(cancellationToken); + + #endregion + + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public DistinctEnumerable AsValueEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public DistinctEnumerable AsEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public async ValueTask ToArrayAsync(CancellationToken cancellationToken = default) + => (await FillSetAsync(cancellationToken).ConfigureAwait(false)).ToArray(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public async ValueTask> ToArrayAsync(ArrayPool pool, bool clearOnDispose, CancellationToken cancellationToken = default) + => (await FillSetAsync(cancellationToken).ConfigureAwait(false)).ToArray(pool, clearOnDispose); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public async ValueTask> ToListAsync(CancellationToken cancellationToken = default) + => (await FillSetAsync(cancellationToken).ConfigureAwait(false)).ToList(); + + #endregion + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, nint, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, nint?, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, nuint, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, nuint?, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this DistinctEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, DistinctEnumerable.Enumerator, decimal?, decimal>(); + } +} + diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyMemory.cs b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ReadOnlyMemory.cs similarity index 70% rename from NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyMemory.cs rename to NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ReadOnlyMemory.cs index f24fc1bf9..9a7d0fbd2 100644 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ReadOnlyMemory.cs @@ -10,11 +10,11 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - + [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemoryDistinctEnumerable Distinct( + static MemoryDistinctEnumerable Distinct( this ReadOnlyMemory source, - IEqualityComparer? comparer = null) + IEqualityComparer? comparer = default) => new(source, comparer); [StructLayout(LayoutKind.Auto)] @@ -28,12 +28,14 @@ internal MemoryDistinctEnumerable(ReadOnlyMemory source, IEqualityCompa => (this.source, this.comparer) = (source, comparer); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); @@ -83,7 +85,7 @@ public void Dispose() => set.Dispose(); } - readonly Set GetSet() + Set GetSet() { var set = new Set(comparer); foreach (var t in source.Span) @@ -91,20 +93,38 @@ public void Dispose() return set; } + #region Aggregation + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() + public int Count() => source switch { { Length: 0 } => 0, _ => GetSet().Count }; + + #endregion + + #region Quantifier [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any() - => source is not 0; + public bool Any() + => source.Length is not 0; + + #endregion + + #region Conversion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public MemoryDistinctEnumerable AsValueEnumerable() + => this; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly TSource[] ToArray() + public MemoryDistinctEnumerable AsEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TSource[] ToArray() => source switch { { Length: 0 } => Array.Empty(), @@ -112,43 +132,19 @@ public void Dispose() }; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly IMemoryOwner ToArray(MemoryPool pool) - => source switch - { - { Length: 0 } => pool.Rent(0), - _ => GetSet().ToArray(pool) - }; + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => GetSet().ToArray(pool, clearOnDispose); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly List ToList() + public List ToList() => source switch { // ReSharper disable once HeapView.ObjectAllocation.Evident { Length: 0 } => new List(), _ => GetSet().ToList() }; - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - using var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } + + #endregion } } } diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ReadOnlySpan.cs similarity index 83% rename from NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ReadOnlySpan.cs index fe64f7c4a..26611f41d 100644 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ReadOnlySpan.cs @@ -8,11 +8,11 @@ namespace NetFabric.Hyperlinq { public static partial class ArrayExtensions { - + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanDistinctEnumerable Distinct( + static SpanDistinctEnumerable Distinct( this ReadOnlySpan source, - IEqualityComparer? comparer = null) + IEqualityComparer? comparer = default) => new(source, comparer); [StructLayout(LayoutKind.Auto)] @@ -29,7 +29,7 @@ internal SpanDistinctEnumerable(ReadOnlySpan source, IEqualityComparer< [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() + public Enumerator GetEnumerator() => new(in this); [StructLayout(LayoutKind.Auto)] @@ -67,7 +67,7 @@ public void Dispose() => set.Dispose(); } - readonly Set GetSet() + Set GetSet() { var set = new Set(comparer); foreach (var t in source) @@ -76,7 +76,7 @@ public void Dispose() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() + public int Count() => source.Length switch { 0 => 0, @@ -84,11 +84,11 @@ public void Dispose() }; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any() + public bool Any() => source.Length is not 0; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly TSource[] ToArray() + public TSource[] ToArray() => source.Length switch { 0 => Array.Empty(), @@ -96,15 +96,11 @@ public void Dispose() }; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly IMemoryOwner ToArray(MemoryPool pool) - => source.Length switch - { - 0 => pool.Rent(0), - _ => GetSet().ToArray(pool) - }; + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => GetSet().ToArray(pool, clearOnDispose); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly List ToList() + public List ToList() => source.Length switch { // ReSharper disable once HeapView.ObjectAllocation.Evident @@ -112,7 +108,7 @@ public void Dispose() _ => GetSet().ToList() }; - public readonly bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) + public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) { comparer ??= EqualityComparer.Default; diff --git a/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ValueEnumerable.cs new file mode 100644 index 000000000..ca155917e --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ValueEnumerable.cs @@ -0,0 +1,212 @@ +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueEnumerableExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static DistinctEnumerable Distinct( + this TEnumerable source, + IEqualityComparer? comparer = default) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => new(source, comparer); + + [StructLayout(LayoutKind.Auto)] + public readonly partial struct DistinctEnumerable + : IValueEnumerable.Enumerator> + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + { + readonly TEnumerable source; + readonly IEqualityComparer? comparer; + + internal DistinctEnumerable(TEnumerable source, IEqualityComparer? comparer) + => (this.source, this.comparer) = (source, comparer); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() + => new(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation + => new Enumerator(in this); + + [StructLayout(LayoutKind.Auto)] + public struct Enumerator + : IEnumerator + { +#pragma warning disable IDE0044 // Add readonly modifier + TEnumerator enumerator; +#pragma warning restore IDE0044 // Add readonly modifier + readonly IEqualityComparer? comparer; + Set set; + + internal Enumerator(in DistinctEnumerable enumerable) + { + enumerator = enumerable.source.GetEnumerator(); + comparer = enumerable.comparer; + set = new Set(comparer); + } + + public readonly TSource Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => enumerator.Current; + } + readonly TSource IEnumerator.Current + => enumerator.Current; + readonly object? IEnumerator.Current + // ReSharper disable once HeapView.PossibleBoxingAllocation + => enumerator.Current; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + while (enumerator.MoveNext()) + { + if (set.Add(enumerator.Current)) + return true; + } + return false; + } + + [ExcludeFromCodeCoverage] + [DoesNotReturn] + public readonly void Reset() + => Throw.NotSupportedException(); + + public void Dispose() + { + enumerator.Dispose(); + set.Dispose(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + Set GetSet() + { + using var set = new Set(comparer); + using var enumerator = source.GetEnumerator(); + while (enumerator.MoveNext()) + _ = set.Add(enumerator.Current); + return set; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Count() + => GetSet().Count; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Any() + => source.Any(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TSource[] ToArray() + => GetSet().ToArray(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Lease ToArray(ArrayPool pool, bool clearOnDispose = default) + => GetSet().ToArray(pool, clearOnDispose); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public List ToList() + => GetSet().ToList(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, nint, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, nint?, nint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, nuint, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, nuint?, nuint>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this DistinctEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, DistinctEnumerable.Enumerator, decimal?, decimal>(); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ValueReadOnlyCollection.cs new file mode 100644 index 000000000..bac8fe6d2 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ValueReadOnlyCollection.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyCollectionExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueEnumerableExtensions.DistinctEnumerable Distinct( + this TEnumerable source, + IEqualityComparer? comparer = default) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => ValueEnumerableExtensions.Distinct(source, comparer); + } +} + diff --git a/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ValueReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ValueReadOnlyList.cs new file mode 100644 index 000000000..dc8954e86 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Set/Distinct/Distinct.ValueReadOnlyList.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static partial class ValueReadOnlyListExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueEnumerableExtensions.DistinctEnumerable Distinct( + this TEnumerable source, + IEqualityComparer? comparer = default) + where TEnumerable : IValueReadOnlyList + where TEnumerator : struct, IEnumerator + => ValueReadOnlyCollectionExtensions.Distinct(source, comparer); + } +} + diff --git a/NetFabric.Hyperlinq/Set/Distinct/Set.cs b/NetFabric.Hyperlinq.Core/Set/Distinct/Set.cs similarity index 83% rename from NetFabric.Hyperlinq/Set/Distinct/Set.cs rename to NetFabric.Hyperlinq.Core/Set/Distinct/Set.cs index 8f351f569..7a1b2805b 100644 --- a/NetFabric.Hyperlinq/Set/Distinct/Set.cs +++ b/NetFabric.Hyperlinq.Core/Set/Distinct/Set.cs @@ -10,7 +10,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace NetFabric.Hyperlinq @@ -30,6 +29,8 @@ struct Set : ICollection, IDisposable /// readonly IEqualityComparer comparer; + readonly bool useDefaultComparer; + /// /// The hash buckets, which are used to index into the slots. /// @@ -50,6 +51,7 @@ public Set(IEqualityComparer? comparer = default) { bucketsPool = ArrayPool.Shared; slotsPool = ArrayPool.Shared; + useDefaultComparer = comparer.UseDefaultComparer(); this.comparer = comparer ?? EqualityComparer.Default; buckets = default; slots = default; @@ -77,15 +79,14 @@ public bool Add(TElement value) Debug.Assert(buckets is not null); Debug.Assert(slots is not null); - var hashCode = value switch - { - null => 0, - _ => comparer.GetHashCode(value) & 0x7FFFFFFF, - }; - if (Utils.UseDefault(comparer)) + var hashCode = 0; + if (useDefaultComparer) { + if (value is not null) + hashCode = EqualityComparer.Default.GetHashCode(value) & 0x7FFFFFFF; + var index = buckets[hashCode % buckets.Length] - 1; - while (index >= 0) + while (index >= 0 && index < slots.Length) { ref readonly var current = ref slots[index]; if (current.HashCode == hashCode && EqualityComparer.Default.Equals(current.Value, value)) @@ -96,8 +97,11 @@ public bool Add(TElement value) } else { + if (value is not null) + hashCode = comparer.GetHashCode(value) & 0x7FFFFFFF; + var index = buckets[hashCode % buckets.Length] - 1; - while (index >= 0) + while (index >= 0 && index < slots.Length) { ref readonly var current = ref slots[index]; if (current.HashCode == hashCode && comparer.Equals(current.Value, value)) @@ -166,9 +170,9 @@ void Resize() return array; } - public readonly IMemoryOwner ToArray(MemoryPool pool) + public readonly Lease ToArray(ArrayPool pool, bool clearOnDispose) { - var result = pool.RentSliced(Count); + var result = pool.Lease(Count, clearOnDispose); CopyTo(result.Memory.Span); return result; } @@ -180,6 +184,7 @@ void Resize() public readonly List ToList() => Count switch { + // ReSharper disable once HeapView.ObjectAllocation.Evident 0 => new List(), _ => ToArray().AsList() }; @@ -194,10 +199,14 @@ void Resize() public readonly void CopyTo(Span span) { - if (slots is null) return; + if (Count is 0) + return; + + if (span.Length < Count) + Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - var source = slots.AsSpan().Slice(0, Count); - for (var index = 0; index < source.Length && index < span.Length; index++) + var source = slots!.AsSpan(0, Count); + for (var index = 0; index < source.Length; index++) { ref readonly var slot = ref source[index]; span[index] = slot.Value; @@ -205,25 +214,25 @@ void Resize() } public readonly void CopyTo(TElement[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); + => CopyTo(array.AsSpan(arrayIndex)); [ExcludeFromCodeCoverage] - void ICollection.Add(TElement item) + readonly void ICollection.Add(TElement item) => Throw.NotSupportedException(); [ExcludeFromCodeCoverage] - void ICollection.Clear() + readonly void ICollection.Clear() => Throw.NotSupportedException(); [ExcludeFromCodeCoverage] - bool ICollection.Contains(TElement item) + readonly bool ICollection.Contains(TElement item) => Throw.NotSupportedException(); [ExcludeFromCodeCoverage] - bool ICollection.Remove(TElement item) + readonly bool ICollection.Remove(TElement item) => Throw.NotSupportedException(); [ExcludeFromCodeCoverage] - IEnumerator IEnumerable.GetEnumerator() + readonly IEnumerator IEnumerable.GetEnumerator() => Throw.NotSupportedException>(); [ExcludeFromCodeCoverage] - IEnumerator IEnumerable.GetEnumerator() + readonly IEnumerator IEnumerable.GetEnumerator() => Throw.NotSupportedException(); /// diff --git a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ArrayBuilder.cs b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ArrayBuilder.cs similarity index 50% rename from NetFabric.Hyperlinq/Utils/ArrayBuilder/ArrayBuilder.cs rename to NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ArrayBuilder.cs index 5f520ef37..36e8ecdcf 100644 --- a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ArrayBuilder.cs +++ b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ArrayBuilder.cs @@ -7,7 +7,8 @@ using System; using System.Buffers; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace NetFabric.Hyperlinq { @@ -15,6 +16,7 @@ namespace NetFabric.Hyperlinq /// Helper type for avoiding allocations while building arrays. /// /// The element type. + [StructLayout(LayoutKind.Auto)] struct ArrayBuilder : IDisposable { @@ -22,7 +24,8 @@ struct ArrayBuilder const int maxCoreClrArrayLength = 0x7fefffff; // For byte arrays the limit is slightly larger readonly ArrayPool pool; - T[]? buffer; // Starts out null, initialized on first Add. + T[] buffer; + int index; /// /// Initializes the with a specified capacity. @@ -33,113 +36,83 @@ public ArrayBuilder(int capacity, ArrayPool pool) { Debug.Assert(capacity >= 0); if (capacity > 0) - { buffer = this.pool.Rent(capacity); - } } public ArrayBuilder(ArrayPool pool) { this.pool = pool; - buffer = default; - Count = 0; + buffer = Array.Empty(); + index = 0; } - /// - /// Gets the number of items this instance can store without re-allocating, - /// or 0 if the backing array is null. - /// - public int Capacity - => buffer?.Length ?? 0; - /// /// Gets the number of items in the array currently in use. /// - public int Count { get; private set; } + // ReSharper disable once ConvertToAutoPropertyWithPrivateSetter + public int Count => index; - /// - /// Gets or sets the item at a certain index in the array. - /// - /// The index into the array. - // public T this[int index] - // { - // get - // { - // Debug.Assert(index >= 0 && index < Count); - // return buffer![index]; - // } - // } - - public readonly Span AsSpan() - => buffer!.AsSpan().Slice(0, Count); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ReadOnlySpan AsSpan() + => buffer.AsSpan(0, index); /// /// Adds an item to the backing array, resizing it if necessary. /// /// The item to add. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(T item) { - if (Count == Capacity) + var buffer = this.buffer; + var index = this.index; + + // Must be >= and not == to enable range check elimination + if ((uint)index >= (uint)buffer.Length) { - EnsureCapacity(Count + 1); + AddWithBufferAllocation(item); + } + else + { + buffer[index] = item; + this.index = index + 1; } - - UncheckedAdd(item); } - - /// - /// Adds an item to the backing array, without checking if there is room. - /// - /// The item to add. - /// - /// Use this method if you know there is enough space in the - /// for another item, and you are writing performance-sensitive code. - /// - public void UncheckedAdd(T item) + + // Non-inline to improve code quality as uncommon path + [MethodImpl(MethodImplOptions.NoInlining)] + void AddWithBufferAllocation(T item) { - Debug.Assert(buffer is not null); - Debug.Assert(Count < Capacity); - - buffer[Count++] = item; + EnsureCapacity(index + 1); + buffer[index++] = item; } void EnsureCapacity(int minimum) { - Debug.Assert(minimum > Capacity); + Debug.Assert(minimum > index); - var capacity = Capacity; - var nextCapacity = capacity switch - { - 0 => defaultMinCapacity, - _ => 2 * capacity, - }; + var capacity = index; + var nextCapacity = capacity is 0 + ? defaultMinCapacity + : 2 * capacity; if ((uint)nextCapacity > (uint)maxCoreClrArrayLength) - { nextCapacity = Math.Max(capacity + 1, maxCoreClrArrayLength); - } nextCapacity = Math.Max(nextCapacity, minimum); var next = pool.Rent(nextCapacity); - try - { - if (buffer is not null) - { - Array.Copy(buffer, next, Count); - } - } - finally + if (index is not 0) { - if (buffer is not null) - pool.Return(buffer); - buffer = next; + buffer.AsSpan().CopyTo(next.AsSpan(index)); + pool.Return(buffer); } + + buffer = next; } public readonly void Dispose() { - if (buffer is not null) + if (index is not 0) pool.Return(buffer); } } diff --git a/NetFabric.Hyperlinq/Utils/ArrayBuilder/LargeArrayBuilder.cs b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/LargeArrayBuilder.cs similarity index 59% rename from NetFabric.Hyperlinq/Utils/ArrayBuilder/LargeArrayBuilder.cs rename to NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/LargeArrayBuilder.cs index fc7ce037a..ebe162eba 100644 --- a/NetFabric.Hyperlinq/Utils/ArrayBuilder/LargeArrayBuilder.cs +++ b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/LargeArrayBuilder.cs @@ -11,6 +11,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace NetFabric.Hyperlinq { @@ -18,6 +19,7 @@ namespace NetFabric.Hyperlinq /// Helper type for building dynamically-sized arrays while minimizing allocations and copying. /// /// The element type. + [StructLayout(LayoutKind.Auto)] struct LargeArrayBuilder : ICollection , IDisposable @@ -25,18 +27,18 @@ struct LargeArrayBuilder const int defaultMinCapacity = 4; readonly ArrayPool pool; + readonly bool clearOnDispose; readonly int maxCapacity; // The maximum capacity this builder can have. ArrayBuilder buffers; // After ResizeLimit * 2, we store previous buffers we've filled out here. T[] current; // Current buffer we're reading into. If _count <= ResizeLimit, this is _first. int index; // Index into the current buffer. - int storedCount; // Number of items stored in buffers. + int count; // Total number of items stored /// /// Constructs a new builder. /// - /// Pass true. - public LargeArrayBuilder(ArrayPool pool) - : this(maxCapacity: int.MaxValue, pool: pool, arrayBuilderPool: ArrayPool.Shared) + public LargeArrayBuilder(ArrayPool pool, bool clearOnDispose) + : this(maxCapacity: int.MaxValue, pool: pool, arrayBuilderPool: ArrayPool.Shared, clearOnDispose) { } @@ -47,56 +49,57 @@ public LargeArrayBuilder(ArrayPool pool) /// /// Do not add more than items to this builder. /// - public LargeArrayBuilder(int maxCapacity, ArrayPool pool, ArrayPool arrayBuilderPool) + public LargeArrayBuilder(int maxCapacity, ArrayPool pool, ArrayPool arrayBuilderPool, bool clearOnDispose) { Debug.Assert(maxCapacity >= 0); this.pool = pool; + this.clearOnDispose = clearOnDispose; this.maxCapacity = maxCapacity; buffers = new ArrayBuilder(arrayBuilderPool); current = Array.Empty(); index = 0; - storedCount = 0; + count = 0; } /// /// Gets the number of items added to the builder. /// - public readonly int Count - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => storedCount + index; - } + // ReSharper disable once ConvertToAutoPropertyWhenPossible + public int Count => count; /// /// Adds an item to this builder. /// /// The item to add. /// - /// Use if adding to the builder is a bottleneck for your use case. - /// Otherwise, use . - /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(T item) { - Debug.Assert(maxCapacity > Count); + Debug.Assert(maxCapacity > count); + + var index = this.index; + var current = this.current; // Must be >= and not == to enable range check elimination if ((uint)index >= (uint)current.Length) - AllocateBuffer(); + { + AddWithBufferAllocation(item); + } + else + { + current[index] = item; + this.index = index + 1; + } - current[index++] = item; + count++; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddRef(in T item) + + // Non-inline to improve code quality as uncommon path + [MethodImpl(MethodImplOptions.NoInlining)] + void AddWithBufferAllocation(T item) { - Debug.Assert(maxCapacity > Count); - - // Must be >= and not == to enable range check elimination - if ((uint)index >= (uint)current.Length) - AllocateBuffer(); - + AllocateBuffer(); current[index++] = item; } @@ -106,68 +109,47 @@ public void AddRef(in T item) /// The destination array. /// The index in to start copying to. public readonly void CopyTo(T[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - public readonly void CopyTo(Span span) { - var arrayIndex = 0; + var span = array.AsSpan(); foreach (var buffer in buffers.AsSpan()) { - var length = buffer.Length; - buffer.AsSpan().CopyTo(span.Slice(arrayIndex, length)); - - arrayIndex += length; - } - if (arrayIndex < Count) - { - var length = Count - arrayIndex; - current.AsSpan().Slice(0, length).CopyTo(span.Slice(arrayIndex, length)); + buffer.AsSpan().CopyTo(span); + span = span.Slice(buffer.Length); } + if (span.Length is not 0) + current.AsSpan(0, span.Length).CopyTo(span); } - /// - /// Adds an item to this builder. - /// - /// The item to add. - /// - /// Use if adding to the builder is a bottleneck for your use case. - /// Otherwise, use . - /// - [MethodImpl(MethodImplOptions.NoInlining)] - public void SlowAdd(T item) - => Add(item); - /// /// Creates an array from the contents of this builder. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly T[] ToArray() { + if (count is 0) + return Array.Empty(); + // ReSharper disable once HeapView.ObjectAllocation.Evident - var array = new T[Count]; - if (Count is not 0) - CopyTo(array); + var array = Utils.AllocateUninitializedArray(count); + CopyTo(array, 0); return array; } - public readonly IMemoryOwner ToArray(MemoryPool pool) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly Lease ToArray(ArrayPool pool, bool clearOnDispose) { - var result = pool.RentSliced(Count); - if (Count is not 0) - CopyTo(result.Memory.Span); + if (count is 0) + return Lease.Empty(); + + var result = pool.Lease(count, clearOnDispose); + CopyTo(result.Rented, 0); return result; } [MethodImpl(MethodImplOptions.NoInlining)] void AllocateBuffer() { - // - On the first few adds, simply resize _first. - // - When we pass ResizeLimit, allocate ResizeLimit elements for _current - // and start reading into _current. Set _index to 0. - // - When _current runs out of space, add it to _buffers and repeat the - // above step, except with _current.Length * 2. - // - Make sure we never pass _maxCapacity in all of the above steps. - - Debug.Assert((uint)maxCapacity > (uint)Count); + Debug.Assert((uint)maxCapacity > (uint)count); Debug.Assert(index == current.Length, $"{nameof(AllocateBuffer)} was called, but there's more space."); // Example scenario: Let's say _count == 64. @@ -178,11 +160,10 @@ void AllocateBuffer() // the rhs the limit minus the amount we've already allocated. var nextCapacity = defaultMinCapacity; - if (Count is not 0) + if (count is not 0) { buffers.Add(current); - nextCapacity = Math.Min(Count, maxCapacity - Count); - storedCount += index; + nextCapacity = Math.Min(count, maxCapacity - count); } current = pool.Rent(nextCapacity); @@ -191,9 +172,9 @@ void AllocateBuffer() public readonly void Dispose() { - pool.Return(current); + pool.Return(current, clearOnDispose); foreach(var item in buffers.AsSpan()) - pool.Return(item); + pool.Return(item, clearOnDispose); buffers.Dispose(); } @@ -201,16 +182,27 @@ void AllocateBuffer() => true; [ExcludeFromCodeCoverage] - IEnumerator IEnumerable.GetEnumerator() => throw new NotSupportedException(); + readonly IEnumerator IEnumerable.GetEnumerator() + => throw new NotSupportedException(); + [ExcludeFromCodeCoverage] - IEnumerator IEnumerable.GetEnumerator() => throw new NotSupportedException(); + readonly IEnumerator IEnumerable.GetEnumerator() + => throw new NotSupportedException(); + [ExcludeFromCodeCoverage] - void ICollection.Add(T item) => throw new NotSupportedException(); + readonly void ICollection.Add(T item) + => throw new NotSupportedException(); + [ExcludeFromCodeCoverage] - void ICollection.Clear() => throw new NotSupportedException(); + readonly void ICollection.Clear() + => throw new NotSupportedException(); + [ExcludeFromCodeCoverage] - bool ICollection.Contains(T item) => throw new NotSupportedException(); + readonly bool ICollection.Contains(T item) + => throw new NotSupportedException(); + [ExcludeFromCodeCoverage] - bool ICollection.Remove(T item) => throw new NotSupportedException(); + readonly bool ICollection.Remove(T item) + => throw new NotSupportedException(); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlyList.cs b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlyList.cs similarity index 74% rename from NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlyList.cs rename to NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlyList.cs index 0e3ab27c8..585f4adc3 100644 --- a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlyList.cs +++ b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlyList.cs @@ -1,18 +1,17 @@ -using System; -using System.Buffers; +using System.Buffers; using System.Collections.Generic; -using System.Diagnostics; namespace NetFabric.Hyperlinq { public static partial class ReadOnlyListExtensions { - static LargeArrayBuilder ToArrayBuilder(in TList source, TPredicate predicate, int offset, int count, ArrayPool pool) + + static LargeArrayBuilder ToArrayBuilder(in TList source, ArrayPool pool, bool clearOnDispose, TPredicate predicate, int offset, int count) where TList : struct, IReadOnlyList where TPredicate: struct, IFunction { - var builder = new LargeArrayBuilder(pool); + var builder = new LargeArrayBuilder(pool, clearOnDispose); var end = offset + count; for (var index = offset; index < end; index++) { @@ -23,11 +22,12 @@ public static partial class ReadOnlyListExtensions return builder; } - static LargeArrayBuilder ToArrayBuilderAt(in TList source, TPredicate predicate, int offset, int count, ArrayPool pool) + + static LargeArrayBuilder ToArrayBuilderAt(in TList source, ArrayPool pool, bool clearOnDispose, TPredicate predicate, int offset, int count) where TList : struct, IReadOnlyList where TPredicate: struct, IFunction { - var builder = new LargeArrayBuilder(pool); + var builder = new LargeArrayBuilder(pool, clearOnDispose); var end = count; if (offset is 0) { @@ -50,12 +50,13 @@ public static partial class ReadOnlyListExtensions return builder; } - static LargeArrayBuilder ToArrayBuilder(in TList source, TPredicate predicate, TSelector selector, int offset, int count, ArrayPool pool) + + static LargeArrayBuilder ToArrayBuilder(in TList source, ArrayPool pool, bool clearOnDispose, TPredicate predicate, TSelector selector, int offset, int count) where TList : struct, IReadOnlyList where TSelector: struct, IFunction where TPredicate: struct, IFunction { - var builder = new LargeArrayBuilder(pool); + var builder = new LargeArrayBuilder(pool, clearOnDispose); var end = offset + count; for (var index = offset; index < end; index++) { diff --git a/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlySpan.cs new file mode 100644 index 000000000..558e23fff --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlySpan.cs @@ -0,0 +1,50 @@ +using System; +using System.Buffers; + +namespace NetFabric.Hyperlinq +{ + public static partial class ArrayExtensions + { + + + static LargeArrayBuilder ToArrayBuilder(ReadOnlySpan source, ArrayPool arrayPool, bool clearOnDispose, TPredicate predicate) + where TPredicate: struct, IFunction + { + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); + foreach (var item in source) + { + if (predicate.Invoke(item)) + builder.Add(item); + } + return builder; + } + + + static LargeArrayBuilder ToArrayBuilderAt(ReadOnlySpan source, ArrayPool arrayPool, bool clearOnDispose, TPredicate predicate) + where TPredicate: struct, IFunction + { + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); + for (var index = 0; index < source.Length; index++) + { + var item = source[index]; + if (predicate.Invoke(item, index)) + builder.Add(item); + } + return builder; + } + + + static LargeArrayBuilder ToArrayBuilder(ReadOnlySpan source, ArrayPool arrayPool, bool clearOnDispose, TPredicate predicate, TSelector selector) + where TPredicate: struct, IFunction + where TSelector: struct, IFunction + { + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); + foreach (var item in source) + { + if (predicate.Invoke(item)) + builder.Add(selector.Invoke(item)); + } + return builder; + } + } +} diff --git a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.ValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilder.ValueEnumerable.cs similarity index 74% rename from NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.ValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilder.ValueEnumerable.cs index 137d701a3..c85c6972c 100644 --- a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilder.ValueEnumerable.cs @@ -1,30 +1,32 @@ -using System; -using System.Buffers; +using System.Buffers; using System.Collections.Generic; -using System.Diagnostics; namespace NetFabric.Hyperlinq { public static partial class ValueEnumerableExtensions { - static LargeArrayBuilder ToArrayBuilder(TEnumerable source, ArrayPool arrayPool) + internal static LargeArrayBuilder ToArrayBuilder(TEnumerable source, ArrayPool arrayPool, bool clearOnDispose) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); using var enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) - builder.Add(enumerator.Current); + { + var item = enumerator.Current; + builder.Add(item); + } return builder; } - static LargeArrayBuilder ToArrayBuilder(TEnumerable source, TPredicate predicate, ArrayPool arrayPool) + + static LargeArrayBuilder ToArrayBuilder(TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); using var enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { @@ -35,12 +37,13 @@ public static partial class ValueEnumerableExtensions return builder; } - static LargeArrayBuilder ToArrayBuilderAt(TEnumerable source, TPredicate predicate, ArrayPool arrayPool) + + static LargeArrayBuilder ToArrayBuilderAt(TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, TPredicate predicate) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); using var enumerator = source.GetEnumerator(); for (var index = 0; enumerator.MoveNext(); index++) { @@ -51,40 +54,49 @@ public static partial class ValueEnumerableExtensions return builder; } - static LargeArrayBuilder ToArrayBuilder(TEnumerable source, TSelector selector, ArrayPool arrayPool) + + static LargeArrayBuilder ToArrayBuilder(TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); using var enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) - builder.Add(selector.Invoke(enumerator.Current)); + { + var item = enumerator.Current; + builder.Add(selector.Invoke(item)); + } return builder; } - static LargeArrayBuilder ToArrayBuilderAt(TEnumerable source, TSelector selector, ArrayPool arrayPool) + + static LargeArrayBuilder ToArrayBuilderAt(TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TSelector : struct, IFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); using var enumerator = source.GetEnumerator(); checked { for (var index = 0; enumerator.MoveNext(); index++) - builder.Add(selector.Invoke(enumerator.Current, index)); + { + var item = enumerator.Current; + builder.Add(selector.Invoke(item, index)); + } } return builder; } - static LargeArrayBuilder ToArrayBuilder(TEnumerable source, TPredicate predicate, TSelector selector, ArrayPool arrayPool) + + static LargeArrayBuilder ToArrayBuilder(TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, TPredicate predicate, TSelector selector) where TEnumerable : IValueEnumerable where TEnumerator : struct, IEnumerator where TPredicate : struct, IFunction where TSelector : struct, IFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); using var enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { diff --git a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilderAsync.AsyncValueEnumerable.cs similarity index 87% rename from NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.AsyncValueEnumerable.cs rename to NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilderAsync.AsyncValueEnumerable.cs index 5369a6714..f4e6689a5 100644 --- a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq.Core/Utils/ArrayBuilder/ToArrayBuilderAsync.AsyncValueEnumerable.cs @@ -1,7 +1,5 @@ -using System; -using System.Buffers; +using System.Buffers; using System.Collections.Generic; -using System.Diagnostics; using System.Threading; using System.Threading.Tasks; @@ -10,11 +8,11 @@ namespace NetFabric.Hyperlinq public static partial class AsyncValueEnumerableExtensions { - static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, ArrayPool arrayPool, CancellationToken cancellationToken) + static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, CancellationToken cancellationToken) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); var enumerator = source.GetAsyncEnumerator(cancellationToken); try { @@ -31,12 +29,13 @@ public static partial class AsyncValueEnumerableExtensions return builder; } - static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, TPredicate predicate, ArrayPool arrayPool, CancellationToken cancellationToken) + + static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); var enumerator = source.GetAsyncEnumerator(cancellationToken); try { @@ -56,12 +55,13 @@ public static partial class AsyncValueEnumerableExtensions return builder; } - static async ValueTask> ToArrayBuilderAtAsync(this TEnumerable source, TPredicate predicate, ArrayPool arrayPool, CancellationToken cancellationToken) + + static async ValueTask> ToArrayBuilderAtAsync(this TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, CancellationToken cancellationToken, TPredicate predicate) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); var enumerator = source.GetAsyncEnumerator(cancellationToken); try { @@ -84,12 +84,13 @@ public static partial class AsyncValueEnumerableExtensions return builder; } - static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, TSelector selector, ArrayPool arrayPool, CancellationToken cancellationToken) + + static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); var enumerator = source.GetAsyncEnumerator(cancellationToken); try { @@ -107,12 +108,13 @@ public static partial class AsyncValueEnumerableExtensions return builder; } - static async ValueTask> ToArrayBuilderAtAsync(this TEnumerable source, TSelector selector, ArrayPool arrayPool, CancellationToken cancellationToken) + + static async ValueTask> ToArrayBuilderAtAsync(this TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, CancellationToken cancellationToken, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TSelector : struct, IAsyncFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); var enumerator = source.GetAsyncEnumerator(cancellationToken); try { @@ -133,13 +135,14 @@ public static partial class AsyncValueEnumerableExtensions return builder; } - static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, TPredicate predicate, TSelector selector, ArrayPool arrayPool, CancellationToken cancellationToken) + + static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, ArrayPool arrayPool, bool clearOnDispose, CancellationToken cancellationToken, TPredicate predicate, TSelector selector) where TEnumerable : IAsyncValueEnumerable where TEnumerator : struct, IAsyncEnumerator where TPredicate : struct, IAsyncFunction where TSelector : struct, IAsyncFunction { - var builder = new LargeArrayBuilder(arrayPool); + var builder = new LargeArrayBuilder(arrayPool, clearOnDispose); var enumerator = source.GetAsyncEnumerator(cancellationToken); try { diff --git a/NetFabric.Hyperlinq.Core/Utils/ArrayExtensions.cs b/NetFabric.Hyperlinq.Core/Utils/ArrayExtensions.cs new file mode 100644 index 000000000..bdaa467ae --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/ArrayExtensions.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + static class InternalArrayExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan AsReadOnlySpan(this T[] source) + => source; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlyMemory AsReadOnlyMemory(this T[] source) + => source; + } +} diff --git a/NetFabric.Hyperlinq.Core/Utils/ArrayPoolExtensions.cs b/NetFabric.Hyperlinq.Core/Utils/ArrayPoolExtensions.cs new file mode 100644 index 000000000..3d9d7ae9e --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/ArrayPoolExtensions.cs @@ -0,0 +1,16 @@ +using System; +using System.Buffers; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + public static class ArrayPoolExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Lease Lease(this ArrayPool pool, int length, bool clearOnDispose = default) + => length < 0 + ? Throw.ArgumentOutOfRangeException>(nameof(length)) + // ReSharper disable once HeapView.ObjectAllocation.Evident + : new Lease(pool, length, clearOnDispose); + } +} diff --git a/NetFabric.Hyperlinq/Utils/ArraySegmentExtensions.cs b/NetFabric.Hyperlinq.Core/Utils/ArraySegmentExtensions.cs similarity index 70% rename from NetFabric.Hyperlinq/Utils/ArraySegmentExtensions.cs rename to NetFabric.Hyperlinq.Core/Utils/ArraySegmentExtensions.cs index 30acec5f6..69fed9d4a 100644 --- a/NetFabric.Hyperlinq/Utils/ArraySegmentExtensions.cs +++ b/NetFabric.Hyperlinq.Core/Utils/ArraySegmentExtensions.cs @@ -12,7 +12,10 @@ public static bool IsEmpty(this in ArraySegment source) // NOTE: Inner array can only be null if length is zero. Should validate before calling this method. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsWhole(this in ArraySegment source) - => source.Count == source.Array!.Length; + => source.Count == source.Array!.Length; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan AsReadOnlySpan(this in ArraySegment source) + => source.AsSpan(); } } diff --git a/NetFabric.Hyperlinq/Utils/BooleanExtensions.cs b/NetFabric.Hyperlinq.Core/Utils/BooleanExtensions.cs similarity index 84% rename from NetFabric.Hyperlinq/Utils/BooleanExtensions.cs rename to NetFabric.Hyperlinq.Core/Utils/BooleanExtensions.cs index 0841c41d9..22f201c86 100644 --- a/NetFabric.Hyperlinq/Utils/BooleanExtensions.cs +++ b/NetFabric.Hyperlinq.Core/Utils/BooleanExtensions.cs @@ -1,5 +1,4 @@ -using System; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { diff --git a/NetFabric.Hyperlinq/Utils/Copy/Copy.Range.cs b/NetFabric.Hyperlinq.Core/Utils/Copy/Copy.Range.cs similarity index 96% rename from NetFabric.Hyperlinq/Utils/Copy/Copy.Range.cs rename to NetFabric.Hyperlinq.Core/Utils/Copy/Copy.Range.cs index a19e81484..2ebdba04b 100644 --- a/NetFabric.Hyperlinq/Utils/Copy/Copy.Range.cs +++ b/NetFabric.Hyperlinq.Core/Utils/Copy/Copy.Range.cs @@ -15,18 +15,18 @@ public static void CopyRange(int start, int count, Span destination) destination = destination.Slice(0, count); - if (Vector.IsHardwareAccelerated && count > Vector.Count * 2) + if (Vector.IsHardwareAccelerated && count >= Vector.Count) { var destinationVectors = MemoryMarshal.Cast>(destination); if (start is 0) { - for (var index = 0; index < Vector.Count && index < destination.Length; index++) + for (var index = 0; index < Vector.Count; index++) destination[index] = index; } else { - for (var index = 0; index < Vector.Count && index < destination.Length; index++) + for (var index = 0; index < Vector.Count; index++) destination[index] = index + start; } diff --git a/NetFabric.Hyperlinq/Utils/Copy/Copy.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Utils/Copy/Copy.ReadOnlySpan.cs similarity index 66% rename from NetFabric.Hyperlinq/Utils/Copy/Copy.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Utils/Copy/Copy.ReadOnlySpan.cs index 729ed969b..57fd57f97 100644 --- a/NetFabric.Hyperlinq/Utils/Copy/Copy.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Utils/Copy/Copy.ReadOnlySpan.cs @@ -22,7 +22,7 @@ public static void Copy(ReadOnlySpan source, Span des { Debug.Assert(destination.Length >= source.Length); - for (var index = 0; index < source.Length && index < destination.Length; index++) + for (var index = 0; index < source.Length; index++) { var item = source[index]; destination[index] = selector.Invoke(item); @@ -50,7 +50,7 @@ public static void Copy(ReadOnlySpan source, Span des destinationVectors[index] = vectorSelector.Invoke(sourceVector); } - for (var index = source.Length - (source.Length % Vector.Count); index < source.Length && index < destination.Length; index++) + for (var index = source.Length - (source.Length % Vector.Count); index < source.Length; index++) { var item = source[index]; destination[index] = selector.Invoke(item); @@ -58,7 +58,7 @@ public static void Copy(ReadOnlySpan source, Span des } else { - for (var index = 0; index < source.Length && index < destination.Length; index++) + for (var index = 0; index < source.Length; index++) { var item = source[index]; destination[index] = selector.Invoke(item); @@ -66,43 +66,17 @@ public static void Copy(ReadOnlySpan source, Span des } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CopyRef(ReadOnlySpan source, Span destination, TSelector selector) - where TSelector : struct, IFunctionIn - { - Debug.Assert(destination.Length >= source.Length); - - for (var index = 0; index < source.Length && index < destination.Length; index++) - { - ref readonly var item = ref source[index]; - destination[index] = selector.Invoke(in item); - } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyAt(ReadOnlySpan source, Span destination, TSelector selector) where TSelector : struct, IFunction { Debug.Assert(destination.Length >= source.Length); - for (var index = 0; index < source.Length && index < destination.Length; index++) + for (var index = 0; index < source.Length; index++) { var item = source[index]; destination[index] = selector.Invoke(item, index); } } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CopyAtRef(ReadOnlySpan source, Span destination, TSelector selector) - where TSelector : struct, IFunctionIn - { - Debug.Assert(destination.Length >= source.Length); - - for (var index = 0; index < source.Length && index < destination.Length; index++) - { - ref readonly var item = ref source[index]; - destination[index] = selector.Invoke(in item, index); - } - } } } diff --git a/NetFabric.Hyperlinq/Utils/Copy/Copy.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Utils/Copy/Copy.ValueReadOnlyCollection.cs similarity index 86% rename from NetFabric.Hyperlinq/Utils/Copy/Copy.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq.Core/Utils/Copy/Copy.ValueReadOnlyCollection.cs index 4cc30f807..b2b6d8070 100644 --- a/NetFabric.Hyperlinq/Utils/Copy/Copy.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq.Core/Utils/Copy/Copy.ValueReadOnlyCollection.cs @@ -15,7 +15,7 @@ static partial class ValueReadOnlyCollectionExtensions using var enumerator = source.GetEnumerator(); checked { - for (var index = 0; enumerator.MoveNext() && index < destination.Length; index++) + for (var index = 0; enumerator.MoveNext(); index++) destination[index] = enumerator.Current; } } @@ -31,7 +31,7 @@ static partial class ValueReadOnlyCollectionExtensions using var enumerator = source.GetEnumerator(); checked { - for (var index = 0; enumerator.MoveNext() && index < destination.Length; index++) + for (var index = 0; enumerator.MoveNext(); index++) destination[index] = selector.Invoke(enumerator.Current); } } @@ -47,7 +47,7 @@ static partial class ValueReadOnlyCollectionExtensions using var enumerator = source.GetEnumerator(); checked { - for (var index = 0; enumerator.MoveNext() && index < destination.Length; index++) + for (var index = 0; enumerator.MoveNext(); index++) destination[index] = selector.Invoke(enumerator.Current, index); } } diff --git a/NetFabric.Hyperlinq/Utils/Default.cs b/NetFabric.Hyperlinq.Core/Utils/Default.cs similarity index 100% rename from NetFabric.Hyperlinq/Utils/Default.cs rename to NetFabric.Hyperlinq.Core/Utils/Default.cs diff --git a/NetFabric.Hyperlinq/Utils/EnumeratorState.cs b/NetFabric.Hyperlinq.Core/Utils/EnumeratorState.cs similarity index 100% rename from NetFabric.Hyperlinq/Utils/EnumeratorState.cs rename to NetFabric.Hyperlinq.Core/Utils/EnumeratorState.cs diff --git a/NetFabric.Hyperlinq/Utils/FunctionCombination/AsyncPredicateCombination.cs b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/AsyncPredicateCombination.cs similarity index 76% rename from NetFabric.Hyperlinq/Utils/FunctionCombination/AsyncPredicateCombination.cs rename to NetFabric.Hyperlinq.Core/Utils/FunctionCombination/AsyncPredicateCombination.cs index 3599ee390..1c826e808 100644 --- a/NetFabric.Hyperlinq/Utils/FunctionCombination/AsyncPredicateCombination.cs +++ b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/AsyncPredicateCombination.cs @@ -10,13 +10,15 @@ public struct AsyncPredicatePredicateCombination where TPredicate2 : struct, IAsyncFunction { +#pragma warning disable IDE0044 // Add readonly modifier TPredicate1 first; TPredicate2 second; +#pragma warning restore IDE0044 // Add readonly modifier public AsyncPredicatePredicateCombination(TPredicate1 first, TPredicate2 second) => (this.first, this.second) = (first, second); - public async ValueTask InvokeAsync(TSource item, CancellationToken cancellationToken) + public readonly async ValueTask InvokeAsync(TSource item, CancellationToken cancellationToken) => await first.InvokeAsync(item, cancellationToken).ConfigureAwait(false) && await second.InvokeAsync(item, cancellationToken).ConfigureAwait(false); } @@ -27,13 +29,15 @@ public struct AsyncPredicatePredicateAtCombination where TPredicate2 : struct, IAsyncFunction { +#pragma warning disable IDE0044 // Add readonly modifier TPredicate1 first; TPredicate2 second; +#pragma warning restore IDE0044 // Add readonly modifier public AsyncPredicatePredicateAtCombination(TPredicate1 first, TPredicate2 second) => (this.first, this.second) = (first, second); - public async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) + public readonly async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) => await first.InvokeAsync(item, cancellationToken).ConfigureAwait(false) && await second.InvokeAsync(item, index, cancellationToken).ConfigureAwait(false); } @@ -44,13 +48,15 @@ public struct AsyncPredicateAtPredicateAtCombination where TPredicate2 : struct, IAsyncFunction { +#pragma warning disable IDE0044 // Add readonly modifier TPredicate1 first; TPredicate2 second; +#pragma warning restore IDE0044 // Add readonly modifier public AsyncPredicateAtPredicateAtCombination(TPredicate1 first, TPredicate2 second) => (this.first, this.second) = (first, second); - public async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) + public readonly async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) => await first.InvokeAsync(item, index, cancellationToken).ConfigureAwait(false) && await second.InvokeAsync(item, index, cancellationToken).ConfigureAwait(false); } diff --git a/NetFabric.Hyperlinq/Utils/FunctionCombination/AsyncSelectorCombination.cs b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/AsyncSelectorCombination.cs similarity index 76% rename from NetFabric.Hyperlinq/Utils/FunctionCombination/AsyncSelectorCombination.cs rename to NetFabric.Hyperlinq.Core/Utils/FunctionCombination/AsyncSelectorCombination.cs index 47ffdeefc..191d83789 100644 --- a/NetFabric.Hyperlinq/Utils/FunctionCombination/AsyncSelectorCombination.cs +++ b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/AsyncSelectorCombination.cs @@ -10,13 +10,15 @@ public struct AsyncSelectorSelectorCombination where TSelector2 : struct, IAsyncFunction { +#pragma warning disable IDE0044 // Add readonly modifier TSelector1 first; TSelector2 second; +#pragma warning restore IDE0044 // Add readonly modifier public AsyncSelectorSelectorCombination(TSelector1 first, TSelector2 second) => (this.first, this.second) = (first, second); - public async ValueTask InvokeAsync(TSource item, CancellationToken cancellationToken) + public readonly async ValueTask InvokeAsync(TSource item, CancellationToken cancellationToken) => await second.InvokeAsync( await first.InvokeAsync(item, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); } @@ -27,13 +29,15 @@ public struct AsyncSelectorAtSelectorCombination where TSelector2 : struct, IAsyncFunction { +#pragma warning disable IDE0044 // Add readonly modifier TSelector1 first; TSelector2 second; +#pragma warning restore IDE0044 // Add readonly modifier public AsyncSelectorAtSelectorCombination(TSelector1 first, TSelector2 second) => (this.first, this.second) = (first, second); - public async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) + public readonly async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) => await second.InvokeAsync( await first.InvokeAsync(item, index, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); @@ -45,13 +49,15 @@ public struct AsyncSelectorSelectorAtCombination where TSelector2 : struct, IAsyncFunction { +#pragma warning disable IDE0044 // Add readonly modifier TSelector1 first; TSelector2 second; +#pragma warning restore IDE0044 // Add readonly modifier public AsyncSelectorSelectorAtCombination(TSelector1 first, TSelector2 second) => (this.first, this.second) = (first, second); - public async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) + public readonly async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) => await second.InvokeAsync( await first.InvokeAsync(item, cancellationToken).ConfigureAwait(false), index, cancellationToken).ConfigureAwait(false); @@ -64,13 +70,15 @@ public struct AsyncSelectorAtSelectorAtCombination where TSelector2 : struct, IAsyncFunction { +#pragma warning disable IDE0044 // Add readonly modifier TSelector1 first; TSelector2 second; +#pragma warning restore IDE0044 // Add readonly modifier public AsyncSelectorAtSelectorAtCombination(TSelector1 first, TSelector2 second) => (this.first, this.second) = (first, second); - public async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) + public readonly async ValueTask InvokeAsync(TSource item, int index, CancellationToken cancellationToken) => await second.InvokeAsync( await first.InvokeAsync(item, index, cancellationToken).ConfigureAwait(false), index, cancellationToken).ConfigureAwait(false); diff --git a/NetFabric.Hyperlinq/Utils/FunctionCombination/PredicateCombination.cs b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/PredicateCombination.cs similarity index 77% rename from NetFabric.Hyperlinq/Utils/FunctionCombination/PredicateCombination.cs rename to NetFabric.Hyperlinq.Core/Utils/FunctionCombination/PredicateCombination.cs index 07542f345..e1e503097 100644 --- a/NetFabric.Hyperlinq/Utils/FunctionCombination/PredicateCombination.cs +++ b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/PredicateCombination.cs @@ -8,13 +8,15 @@ public struct PredicatePredicateCombination where TPredicate1 : struct, IFunction where TPredicate2 : struct, IFunction { +#pragma warning disable IDE0044 // Add readonly modifier TPredicate1 first; TPredicate2 second; +#pragma warning restore IDE0044 // Add readonly modifier public PredicatePredicateCombination(TPredicate1 first, TPredicate2 second) => (this.first, this.second) = (first, second); - public bool Invoke(TSource item) + public readonly bool Invoke(TSource item) => first.Invoke(item) && second.Invoke(item); } @@ -24,13 +26,15 @@ public struct PredicatePredicateAtCombination where TPredicate1 : struct, IFunction where TPredicate2 : struct, IFunction { +#pragma warning disable IDE0044 // Add readonly modifier TPredicate1 first; TPredicate2 second; +#pragma warning restore IDE0044 // Add readonly modifier public PredicatePredicateAtCombination(TPredicate1 first, TPredicate2 second) => (this.first, this.second) = (first, second); - public bool Invoke(TSource item, int index) + public readonly bool Invoke(TSource item, int index) => first.Invoke(item) && second.Invoke(item, index); } @@ -40,13 +44,15 @@ public struct PredicateAtPredicateAtCombination where TPredicate2 : struct, IFunction { +#pragma warning disable IDE0044 // Add readonly modifier TPredicate1 first; TPredicate2 second; +#pragma warning restore IDE0044 // Add readonly modifier public PredicateAtPredicateAtCombination(TPredicate1 first, TPredicate2 second) => (this.first, this.second) = (first, second); - public bool Invoke(TSource item, int index) + public readonly bool Invoke(TSource item, int index) => first.Invoke(item, index) && second.Invoke(item, index); } } diff --git a/NetFabric.Hyperlinq/Utils/FunctionCombination/PredicateInCombination.cs b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/PredicateInCombination.cs similarity index 77% rename from NetFabric.Hyperlinq/Utils/FunctionCombination/PredicateInCombination.cs rename to NetFabric.Hyperlinq.Core/Utils/FunctionCombination/PredicateInCombination.cs index 6b9bd5927..4d1573aa9 100644 --- a/NetFabric.Hyperlinq/Utils/FunctionCombination/PredicateInCombination.cs +++ b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/PredicateInCombination.cs @@ -8,13 +8,15 @@ public struct PredicatePredicateCombinationIn where TPredicate1 : struct, IFunctionIn where TPredicate2 : struct, IFunctionIn { +#pragma warning disable IDE0044 // Add readonly modifier TPredicate1 first; TPredicate2 second; +#pragma warning restore IDE0044 // Add readonly modifier public PredicatePredicateCombinationIn(TPredicate1 first, TPredicate2 second) => (this.first, this.second) = (first, second); - public bool Invoke(in TSource item) + public readonly bool Invoke(in TSource item) => first.Invoke(in item) && second.Invoke(in item); } @@ -24,13 +26,15 @@ public struct PredicatePredicateAtCombinationIn where TPredicate2 : struct, IFunctionIn { +#pragma warning disable IDE0044 // Add readonly modifier TPredicate1 first; TPredicate2 second; +#pragma warning restore IDE0044 // Add readonly modifier public PredicatePredicateAtCombinationIn(TPredicate1 first, TPredicate2 second) => (this.first, this.second) = (first, second); - public bool Invoke(in TSource item, int index) + public readonly bool Invoke(in TSource item, int index) => first.Invoke(in item) && second.Invoke(in item, index); } @@ -40,13 +44,15 @@ public struct PredicateAtPredicateAtCombinationIn where TPredicate2 : struct, IFunctionIn { +#pragma warning disable IDE0044 // Add readonly modifier TPredicate1 first; TPredicate2 second; +#pragma warning restore IDE0044 // Add readonly modifier public PredicateAtPredicateAtCombinationIn(TPredicate1 first, TPredicate2 second) => (this.first, this.second) = (first, second); - public bool Invoke(in TSource item, int index) + public readonly bool Invoke(in TSource item, int index) => first.Invoke(in item, index) && second.Invoke(in item, index); } } diff --git a/NetFabric.Hyperlinq/Utils/FunctionCombination/SelectorCombination.cs b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/SelectorCombination.cs similarity index 77% rename from NetFabric.Hyperlinq/Utils/FunctionCombination/SelectorCombination.cs rename to NetFabric.Hyperlinq.Core/Utils/FunctionCombination/SelectorCombination.cs index 456bb94f0..92d3bb4c1 100644 --- a/NetFabric.Hyperlinq/Utils/FunctionCombination/SelectorCombination.cs +++ b/NetFabric.Hyperlinq.Core/Utils/FunctionCombination/SelectorCombination.cs @@ -8,13 +8,15 @@ public struct SelectorSelectorCombination where TSelector2 : struct, IFunction { +#pragma warning disable IDE0044 // Add readonly modifier TSelector1 first; TSelector2 second; +#pragma warning restore IDE0044 // Add readonly modifier public SelectorSelectorCombination(TSelector1 first, TSelector2 second) => (this.first, this.second) = (first, second); - public TResult Invoke(TSource item) + public readonly TResult Invoke(TSource item) => second.Invoke(first.Invoke(item)); } @@ -24,13 +26,15 @@ public struct SelectorAtSelectorCombination where TSelector2 : struct, IFunction { +#pragma warning disable IDE0044 // Add readonly modifier TSelector1 first; TSelector2 second; +#pragma warning restore IDE0044 // Add readonly modifier public SelectorAtSelectorCombination(TSelector1 first, TSelector2 second) => (this.first, this.second) = (first, second); - public TResult Invoke(TSource item, int index) + public readonly TResult Invoke(TSource item, int index) => second.Invoke(first.Invoke(item, index)); } @@ -40,13 +44,15 @@ public struct SelectorSelectorAtCombination where TSelector2 : struct, IFunction { +#pragma warning disable IDE0044 // Add readonly modifier TSelector1 first; TSelector2 second; +#pragma warning restore IDE0044 // Add readonly modifier public SelectorSelectorAtCombination(TSelector1 first, TSelector2 second) => (this.first, this.second) = (first, second); - public TResult Invoke(TSource item, int index) + public readonly TResult Invoke(TSource item, int index) => second.Invoke(first.Invoke(item), index); } @@ -57,13 +63,15 @@ public struct SelectorAtSelectorAtCombination where TSelector2 : struct, IFunction { +#pragma warning disable IDE0044 // Add readonly modifier TSelector1 first; TSelector2 second; +#pragma warning restore IDE0044 // Add readonly modifier public SelectorAtSelectorAtCombination(TSelector1 first, TSelector2 second) => (this.first, this.second) = (first, second); - public TResult Invoke(TSource item, int index) + public readonly TResult Invoke(TSource item, int index) => second.Invoke(first.Invoke(item, index), index); } } diff --git a/NetFabric.Hyperlinq/Utils/IndexOf/IndexOf.ReadOnlySpan.cs b/NetFabric.Hyperlinq.Core/Utils/IndexOf/IndexOf.ReadOnlySpan.cs similarity index 57% rename from NetFabric.Hyperlinq/Utils/IndexOf/IndexOf.ReadOnlySpan.cs rename to NetFabric.Hyperlinq.Core/Utils/IndexOf/IndexOf.ReadOnlySpan.cs index 35c8c85ce..ac734b057 100644 --- a/NetFabric.Hyperlinq/Utils/IndexOf/IndexOf.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq.Core/Utils/IndexOf/IndexOf.ReadOnlySpan.cs @@ -9,7 +9,7 @@ static partial class ArrayExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf(ReadOnlySpan source, TSource item) { - if (source.Length is 0) + if (source.IsEmpty) return -1; if (Utils.IsValueType()) @@ -39,7 +39,7 @@ public static int IndexOf(ReadOnlySpan source, TSource item) public static int IndexOf(ReadOnlySpan source, TResult item, TSelector selector) where TSelector : struct, IFunction { - if (source.Length is 0) + if (source.IsEmpty) return -1; if (Utils.IsValueType()) @@ -65,42 +65,12 @@ public static int IndexOf(ReadOnlySpan source, TSource item) return -1; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int IndexOfRef(ReadOnlySpan source, TResult item, TSelector selector) - where TSelector : struct, IFunctionIn - { - if (source.Length is 0) - return -1; - - if (Utils.IsValueType()) - { - for (var index = 0; index < source.Length; index++) - { - ref readonly var arrayItem = ref source[index]; - if (EqualityComparer.Default.Equals(selector.Invoke(in arrayItem), item)) - return index; - } - } - else - { - var defaultComparer = EqualityComparer.Default; - for (var index = 0; index < source.Length; index++) - { - ref readonly var arrayItem = ref source[index]; - if (defaultComparer.Equals(selector.Invoke(in arrayItem), item)) - return index; - } - } - - return -1; - } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAt(ReadOnlySpan source, TResult item, TSelector selector) where TSelector : struct, IFunction { - if (source.Length is 0) + if (source.IsEmpty) return -1; if (Utils.IsValueType()) @@ -126,35 +96,5 @@ public static int IndexOf(ReadOnlySpan source, TSource item) return -1; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int IndexOfAtRef(ReadOnlySpan source, TResult item, TSelector selector) - where TSelector : struct, IFunctionIn - { - if (source.Length is 0) - return -1; - - if (Utils.IsValueType()) - { - for (var index = 0; index < source.Length; index++) - { - ref readonly var arrayItem = ref source[index]; - if (EqualityComparer.Default.Equals(selector.Invoke(in arrayItem, index), item)) - return index; - } - } - else - { - var defaultComparer = EqualityComparer.Default; - for (var index = 0; index < source.Length; index++) - { - ref readonly var arrayItem = ref source[index]; - if (defaultComparer.Equals(selector.Invoke(in arrayItem, index), item)) - return index; - } - } - - return -1; - } - } } diff --git a/NetFabric.Hyperlinq.Core/Utils/IndexOf/IndexOf.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.Core/Utils/IndexOf/IndexOf.ValueReadOnlyCollection.cs new file mode 100644 index 000000000..d901a4294 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/IndexOf/IndexOf.ValueReadOnlyCollection.cs @@ -0,0 +1,103 @@ +using System.Collections.Generic; + +namespace NetFabric.Hyperlinq +{ + static partial class ValueReadOnlyCollectionExtensions + { + public static int IndexOf(TEnumerable source, TSource item) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + { + if (source.Count is 0) + return -1; + + using var enumerator = source.GetEnumerator(); + if (Utils.IsValueType()) + { + for (var index = 0; enumerator.MoveNext(); index++) + { + var current = enumerator.Current; + if (EqualityComparer.Default.Equals(current, item)) + return index; + } + } + else + { + var defaultComparer = EqualityComparer.Default; + for (var index = 0; enumerator.MoveNext(); index++) + { + var current = enumerator.Current; + if (defaultComparer.Equals(current, item)) + return index; + } + } + + return -1; + } + + public static int IndexOf(TEnumerable source, TResult item, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + if (source.Count is 0) + return -1; + + using var enumerator = source.GetEnumerator(); + if (Utils.IsValueType()) + { + for (var index = 0; enumerator.MoveNext(); index++) + { + var current = enumerator.Current; + if (EqualityComparer.Default.Equals(selector.Invoke(current), item)) + return index; + } + } + else + { + var defaultComparer = EqualityComparer.Default; + for (var index = 0; enumerator.MoveNext(); index++) + { + var current = enumerator.Current; + if (defaultComparer.Equals(selector.Invoke(current), item)) + return index; + } + } + + return -1; + } + + + public static int IndexOfAt(TEnumerable source, TResult item, TSelector selector) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + where TSelector : struct, IFunction + { + if (source.Count is 0) + return -1; + + using var enumerator = source.GetEnumerator(); + if (Utils.IsValueType()) + { + for (var index = 0; enumerator.MoveNext(); index++) + { + var current = enumerator.Current; + if (EqualityComparer.Default.Equals(selector.Invoke(current, index), item)) + return index; + } + } + else + { + var defaultComparer = EqualityComparer.Default; + + for (var index = 0; enumerator.MoveNext(); index++) + { + var current = enumerator.Current; + if (defaultComparer.Equals(selector.Invoke(current, index), item)) + return index; + } + } + return -1; + } + } +} diff --git a/NetFabric.Hyperlinq.Core/Utils/IntExtensions.cs b/NetFabric.Hyperlinq.Core/Utils/IntExtensions.cs new file mode 100644 index 000000000..baf066cd6 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/IntExtensions.cs @@ -0,0 +1,15 @@ +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + static class IntExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsEven(this int value) + => (value & 1) is 0; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsOdd(this int value) + => (value & 1) is not 0; + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.Core/Utils/MemoryExtensions.cs b/NetFabric.Hyperlinq.Core/Utils/MemoryExtensions.cs new file mode 100644 index 000000000..99cfc73b2 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/MemoryExtensions.cs @@ -0,0 +1,12 @@ +using System; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + static class MemoryExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlyMemory AsReadOnlyMemory(this Memory source) + => source; + } +} diff --git a/NetFabric.Hyperlinq.Core/Utils/Scalar.cs b/NetFabric.Hyperlinq.Core/Utils/Scalar.cs new file mode 100644 index 000000000..c77244f9e --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/Scalar.cs @@ -0,0 +1,227 @@ +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + static class Scalar + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TValue Add(TNullableValue a, TValue b) + where TValue : struct + { + if (typeof(TNullableValue) == typeof(int?) && typeof(TValue) == typeof(int)) + return (TValue)(object)(((int?)(object?)a).GetValueOrDefault() + (int)(object)b); + + if (typeof(TNullableValue) == typeof(int) && typeof(TValue) == typeof(int)) + return (TValue)(object)((int)(object)a! + (int)(object)b); + + if (typeof(TNullableValue) == typeof(uint?) && typeof(TValue) == typeof(uint)) + return (TValue)(object)(((uint?)(object?)a).GetValueOrDefault() + (uint)(object)b); + + if (typeof(TNullableValue) == typeof(uint) && typeof(TValue) == typeof(uint)) + return (TValue)(object)((uint)(object)a! + (uint)(object)b); + + if (typeof(TNullableValue) == typeof(nint?) && typeof(TValue) == typeof(nint)) + return (TValue)(object)(((nint?)(object?)a).GetValueOrDefault() + (nint)(object)b); + + if (typeof(TNullableValue) == typeof(nint) && typeof(TValue) == typeof(nint)) + return (TValue)(object)((nint)(object)a! + (nint)(object)b); + + if (typeof(TNullableValue) == typeof(nuint?) && typeof(TValue) == typeof(nuint)) + return (TValue)(object)(((nuint?)(object?)a).GetValueOrDefault() + (nuint)(object)b); + + if (typeof(TNullableValue) == typeof(nuint) && typeof(TValue) == typeof(nuint)) + return (TValue)(object)((nuint)(object)a! + (nuint)(object)b); + + if (typeof(TNullableValue) == typeof(long?) && typeof(TValue) == typeof(long)) + return (TValue)(object)(((long?)(object?)a).GetValueOrDefault() + (long)(object)b); + + if (typeof(TNullableValue) == typeof(long) && typeof(TValue) == typeof(long)) + return (TValue)(object)((long)(object)a! + (long)(object)b); + + if (typeof(TNullableValue) == typeof(float?) && typeof(TValue) == typeof(float)) + return (TValue)(object)(((float?)(object?)a).GetValueOrDefault() + (float)(object)b); + + if (typeof(TNullableValue) == typeof(float) && typeof(TValue) == typeof(float)) + return (TValue)(object)((float)(object)a! + (float)(object)b); + + if (typeof(TNullableValue) == typeof(double?) && typeof(TValue) == typeof(double)) + return (TValue)(object)(((double?)(object?)a).GetValueOrDefault() + (double)(object)b); + + if (typeof(TNullableValue) == typeof(double) && typeof(TValue) == typeof(double)) + return (TValue)(object)((double)(object)a! + (double)(object)b); + + if (typeof(TNullableValue) == typeof(decimal?) && typeof(TValue) == typeof(decimal)) + return (TValue)(object)(((decimal?)(object?)a).GetValueOrDefault() + (decimal)(object)b); + + if (typeof(TNullableValue) == typeof(decimal) && typeof(TValue) == typeof(decimal)) + return (TValue)(object)((decimal)(object)a! + (decimal)(object)b); + + return Throw.NotSupportedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Equals(TValue a, TValue b) + where TValue : struct + { + if (typeof(TValue) == typeof(byte)) + return (byte)(object)a == (byte)(object)b; + + if (typeof(TValue) == typeof(sbyte)) + return (sbyte)(object)a == (sbyte)(object)b; + + if (typeof(TValue) == typeof(short)) + return (short)(object)a == (short)(object)b; + + if (typeof(TValue) == typeof(ushort)) + return (ushort)(object)a == (ushort)(object)b; + + if (typeof(TValue) == typeof(int)) + return (int)(object)a == (int)(object)b; + + if (typeof(TValue) == typeof(uint)) + return (uint)(object)a == (uint)(object)b; + + if (typeof(TValue) == typeof(long)) + return (long)(object)a == (long)(object)b; + + if (typeof(TValue) == typeof(ulong)) + return (ulong)(object)a == (ulong)(object)b; + + if (typeof(TValue) == typeof(float)) + // ReSharper disable once CompareOfFloatsByEqualityOperator + return (float)(object)a == (float)(object)b; + + if (typeof(TValue) == typeof(double)) + // ReSharper disable once CompareOfFloatsByEqualityOperator + return (double)(object)a == (double)(object)b; + + if (typeof(TValue) == typeof(decimal)) + return (decimal)(object)a == (decimal)(object)b; + + return Throw.NotSupportedException(); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TValue GetValueOrDefault(TPredicate predicate, TValue value) + where TPredicate : struct, IFunction + { + if (typeof(TValue) == typeof(int?)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * ((int?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(int)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * (int)(object)value!); + + if (typeof(TValue) == typeof(uint?)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * ((uint?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(uint)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * (uint)(object)value!); + + if (typeof(TValue) == typeof(nint?)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * ((nint?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(nint)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * (nint)(object)value!); + + if (typeof(TValue) == typeof(nuint?)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * ((nuint?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(nuint)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * (nuint)(object)value!); + + if (typeof(TValue) == typeof(long?)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * ((long?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(long)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * (long)(object)value!); + + if (typeof(TValue) == typeof(ulong?)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * ((ulong?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(ulong)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * (ulong)(object)value!); + + if (typeof(TValue) == typeof(float?)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * ((float?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(float)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * (float)(object)value!); + + if (typeof(TValue) == typeof(double?)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * ((double?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(double)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * (double)(object)value!); + + if (typeof(TValue) == typeof(decimal?)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * ((decimal?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(decimal)) + return (TValue)(object)(predicate.Invoke(value).AsByte() * (decimal)(object)value!); + + return Throw.NotSupportedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TValue GetValueOrDefault(TPredicate predicate, TValue value, int index) + where TPredicate : struct, IFunction + { + if (typeof(TValue) == typeof(int?)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * ((int?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(int)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * (int)(object)value!); + + if (typeof(TValue) == typeof(uint?)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * ((uint?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(uint)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * (uint)(object)value!); + + if (typeof(TValue) == typeof(nint?)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * ((nint?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(nint)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * (nint)(object)value!); + + if (typeof(TValue) == typeof(nuint?)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * ((nuint?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(nuint)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * (nuint)(object)value!); + + if (typeof(TValue) == typeof(long?)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * ((long?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(long)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * (long)(object)value!); + + if (typeof(TValue) == typeof(ulong?)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * ((ulong?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(ulong)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * (ulong)(object)value!); + + if (typeof(TValue) == typeof(float?)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * ((float?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(float)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * (float)(object)value!); + + if (typeof(TValue) == typeof(double?)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * ((double?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(double)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * (double)(object)value!); + + if (typeof(TValue) == typeof(decimal?)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * ((decimal?)(object?)value).GetValueOrDefault()); + + if (typeof(TValue) == typeof(decimal)) + return (TValue)(object)(predicate.Invoke(value, index).AsByte() * (decimal)(object)value!); + + return Throw.NotSupportedException(); + } + } +} diff --git a/NetFabric.Hyperlinq.Core/Utils/SpanExtensions.cs b/NetFabric.Hyperlinq.Core/Utils/SpanExtensions.cs new file mode 100644 index 000000000..07b150b9e --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/SpanExtensions.cs @@ -0,0 +1,12 @@ +using System; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + static class SpanExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan AsReadOnlySpan(this Span source) + => source; + } +} diff --git a/NetFabric.Hyperlinq/Utils/Throw.cs b/NetFabric.Hyperlinq.Core/Utils/Throw.cs similarity index 61% rename from NetFabric.Hyperlinq/Utils/Throw.cs rename to NetFabric.Hyperlinq.Core/Utils/Throw.cs index 082ef9f74..8b8ad3075 100644 --- a/NetFabric.Hyperlinq/Utils/Throw.cs +++ b/NetFabric.Hyperlinq.Core/Utils/Throw.cs @@ -1,6 +1,6 @@ using System; using System.Diagnostics.CodeAnalysis; -using System.Runtime.Versioning; +using System.Runtime.CompilerServices; namespace NetFabric.Hyperlinq { @@ -9,43 +9,35 @@ static class Throw { [DoesNotReturn] public static void ArgumentArraySegmentNullException(string paramName) - => throw new ArgumentException(Resource.ArraySegmentNull, paramName); + => throw new ArgumentException(paramName: paramName, message: Resource.ArraySegmentNull); [DoesNotReturn] - public static void ArgumentException(string message, string paramName) - => throw new ArgumentException(message, paramName); + public static void ArgumentException(string paramName, string? message = default) + => throw new ArgumentException(paramName: paramName, message: message); [DoesNotReturn] - public static void ArgumentNullException(string paramName) - => throw new ArgumentNullException(paramName); + public static void ArgumentNullException(string paramName, string? message = default) + => throw new ArgumentNullException(paramName: paramName, message: message); [DoesNotReturn] - public static T ArgumentNullException(string paramName) - => throw new ArgumentNullException(paramName); + public static T ArgumentNullException(string paramName, string? message = default) + => throw new ArgumentNullException(paramName: paramName, message: message); [DoesNotReturn] - public static ref readonly T ArgumentNullExceptionRef(string paramName) - => throw new ArgumentNullException(paramName); + public static ref readonly T ArgumentNullExceptionRef(string paramName, string? message = default) + => throw new ArgumentNullException(paramName: paramName, message: message); [DoesNotReturn] - public static void ArgumentOutOfRangeException(string paramName) - => throw new ArgumentOutOfRangeException(paramName); + public static void ArgumentOutOfRangeException(string paramName, string? message = default) + => throw new ArgumentOutOfRangeException(paramName: paramName, message: message); [DoesNotReturn] - public static T ArgumentOutOfRangeException(string paramName) - => throw new ArgumentOutOfRangeException(paramName); + public static T ArgumentOutOfRangeException(string paramName, string? message = default) + => throw new ArgumentOutOfRangeException(paramName: paramName, message: message); [DoesNotReturn] - public static ref readonly T ArgumentOutOfRangeExceptionRef(string paramName) - => throw new ArgumentOutOfRangeException(paramName); - - [DoesNotReturn] - public static void IndexOutOfRangeException() - => throw new IndexOutOfRangeException(); - - [DoesNotReturn] - public static T IndexOutOfRangeException() - => throw new IndexOutOfRangeException(); + public static ref readonly T ArgumentOutOfRangeExceptionRef(string paramName, string? message = default) + => throw new ArgumentOutOfRangeException(paramName: paramName, message: message); [DoesNotReturn] public static void EmptySequence() @@ -72,11 +64,7 @@ public static T NotSingleSequence() => throw new InvalidOperationException(Resource.NotSingleSequence); [DoesNotReturn] - public static void InvalidOperationException() - => throw new InvalidOperationException(); - - [DoesNotReturn] - public static void InvalidOperationException(string message) + public static void InvalidOperationException(string? message = default) => throw new InvalidOperationException(message); [DoesNotReturn] @@ -90,5 +78,13 @@ public static void NotSupportedException() [DoesNotReturn] public static T NotSupportedException() => throw new NotSupportedException(); + + [DoesNotReturn] + public static void ObjectDisposedException(string objectName) + => throw new ObjectDisposedException(objectName); + + [DoesNotReturn] + public static T ObjectDisposedException(string objectName) + => throw new ObjectDisposedException(objectName); } } diff --git a/NetFabric.Hyperlinq.Core/Utils/ThrowIfArgument.cs b/NetFabric.Hyperlinq.Core/Utils/ThrowIfArgument.cs new file mode 100644 index 000000000..7b48dcff6 --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/ThrowIfArgument.cs @@ -0,0 +1,26 @@ +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + static class ThrowIfArgument + { + // [DebuggerStepThrough] + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public static void Null([DoesNotReturnIf()]T paramValue, /*[CallerArgumentExpression("paramValue")]*/ string paramName) + // { + // if (paramValue is null) + // Throw.ArgumentNullException(paramName); + // } + + [DebuggerStepThrough] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void OutOfRange(int paramValue, int maxValue, /*[CallerArgumentExpression("paramValue")]*/ string paramName) + { + if ((uint)paramValue >= (uint)maxValue) + Throw.ArgumentOutOfRangeException(paramName); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Utils/Utils.AllocateUninitializedArray.cs b/NetFabric.Hyperlinq.Core/Utils/Utils.AllocateUninitializedArray.cs similarity index 64% rename from NetFabric.Hyperlinq/Utils/Utils.AllocateUninitializedArray.cs rename to NetFabric.Hyperlinq.Core/Utils/Utils.AllocateUninitializedArray.cs index 596d11ce3..56611920d 100644 --- a/NetFabric.Hyperlinq/Utils/Utils.AllocateUninitializedArray.cs +++ b/NetFabric.Hyperlinq.Core/Utils/Utils.AllocateUninitializedArray.cs @@ -5,11 +5,13 @@ namespace NetFabric.Hyperlinq { static partial class Utils { + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T[] AllocateUninitializedArray(int count) -#if NET5_0 - => GC.AllocateUninitializedArray(count); +#if NET5_0_OR_GREATER + => GC.AllocateUninitializedArray(count, pinned: false); #else + // ReSharper disable once HeapView.ObjectAllocation.Evident => new T[count]; #endif } diff --git a/NetFabric.Hyperlinq/Utils/Utils.EqualityComparer.cs b/NetFabric.Hyperlinq.Core/Utils/Utils.EqualityComparer.cs similarity index 58% rename from NetFabric.Hyperlinq/Utils/Utils.EqualityComparer.cs rename to NetFabric.Hyperlinq.Core/Utils/Utils.EqualityComparer.cs index 51381796a..8236f5895 100644 --- a/NetFabric.Hyperlinq/Utils/Utils.EqualityComparer.cs +++ b/NetFabric.Hyperlinq.Core/Utils/Utils.EqualityComparer.cs @@ -7,10 +7,10 @@ static partial class Utils { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsValueType() - => default(T) is object; + => default(T) is not null; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool UseDefault(IEqualityComparer? comparer) - => IsValueType() && (comparer is null || ReferenceEquals(comparer, EqualityComparer.Default)); + public static bool UseDefaultComparer(this IEqualityComparer? comparer) + => comparer is null || ReferenceEquals(comparer, EqualityComparer.Default); } } diff --git a/NetFabric.Hyperlinq/Utils/Utils.SkipTake.cs b/NetFabric.Hyperlinq.Core/Utils/Utils.SkipTake.cs similarity index 100% rename from NetFabric.Hyperlinq/Utils/Utils.SkipTake.cs rename to NetFabric.Hyperlinq.Core/Utils/Utils.SkipTake.cs diff --git a/NetFabric.Hyperlinq.Core/Utils/VectorExtensions.cs b/NetFabric.Hyperlinq.Core/Utils/VectorExtensions.cs new file mode 100644 index 000000000..bbbff542a --- /dev/null +++ b/NetFabric.Hyperlinq.Core/Utils/VectorExtensions.cs @@ -0,0 +1,18 @@ +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq +{ + static class VectorExtensions + { + public static T Sum(this Vector vector) + where T : struct + { + ref var item = ref Unsafe.As, T>(ref Unsafe.AsRef(in vector)); + var sum = default(T); + for (var index = 0; index < Vector.Count; index++) + sum = Scalar.Add(Unsafe.Add(ref item, index), sum); + return sum; + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/CollectExtensionMethodsTests.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/CollectExtensionMethodsTests.cs deleted file mode 100644 index 6e6255b90..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/CollectExtensionMethodsTests.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Microsoft.CodeAnalysis; -using NetFabric.Assertive; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Xunit; - -namespace NetFabric.Hyperlinq.SourceGenerator.UnitTests -{ - public class CollectExtensionMethodsTests - { - public static TheoryData ExtensionMethods - => new TheoryData { - { new string[] { "TestData/Source/NoExtensionMethods.cs" }, 0 }, - { new string[] { "TestData/Source/Distinct.ArraySegment.cs" }, 0 }, - { new string[] { "TestData/Source/Where.ArraySegment.cs" }, 0 }, - { new string[] { "TestData/Source/Select.ArraySegment.cs" }, 0 }, - - { new string[] { "TestData/Source/ExtensionMethods.cs" }, 1 }, - { new string[] { "TestData/Source/Count.ValueEnumerable.cs" }, 1 }, - { new string[] { "TestData/Source/Distinct.ValueEnumerable.cs" }, 1 }, - - { new string[] { "TestData/Source/Where.ValueEnumerable.cs" }, 2 }, - { new string[] { "TestData/Source/Select.ValueEnumerable.cs" }, 2 }, - }; - - [Theory] - [MemberData(nameof(ExtensionMethods))] - public async Task ShouldCollectExpectedNumberOfExtensionMethods(string[] paths, int expected) - { - // Arrange - var generator = new OverloadsGenerator(); - var project = Verifier.CreateProject( - paths - .Concat(Directory.EnumerateFiles("TestData/Source/Common", "*.cs", SearchOption.AllDirectories)) - .Select(path => File.ReadAllText(path))); - var compilation = await project.GetCompilationAsync().ConfigureAwait(false); - - // Act - var result = generator.CollectExtensionMethods(compilation!); - - // Assert - _ = result.Values.SelectMany(item => item).Count().Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/GenerateSourceTests.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/GenerateSourceTests.cs deleted file mode 100644 index 4ca6cd257..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/GenerateSourceTests.cs +++ /dev/null @@ -1,237 +0,0 @@ -using Microsoft.CodeAnalysis; -using NetFabric.Assertive; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Xunit; - -namespace NetFabric.Hyperlinq.SourceGenerator.UnitTests -{ - public class GenerateSourceTests - { - public static TheoryData ClassesWithOverloads - => new TheoryData { - new string[] { - "TestData/Source/Count.ValueEnumerable.cs", - }, - new string[] { - "TestData/Source/Where.ValueEnumerable.cs", - }, - new string[] { - "TestData/Source/Select.ValueEnumerable.cs", - }, - }; - - [Theory] - [MemberData(nameof(ClassesWithOverloads))] - public async Task ClassesWithOverloadsShouldNotGenerate(string[] paths) - { - // Arrange - var generator = new OverloadsGenerator(); - var project = Verifier.CreateProject( - paths - .Concat(Directory.EnumerateFiles("TestData/Source/Common", "*.cs", SearchOption.AllDirectories)) - .Select(path => File.ReadAllText(path))); - var compilation = await project.GetCompilationAsync().ConfigureAwait(false); - - // Act - var extensionMethods = generator.CollectExtensionMethods(compilation!); - var result = generator.GenerateSource(compilation!, extensionMethods); - - // Assert - _ = result.Must() - .BeEnumerableOf<(INamedTypeSymbol, INamedTypeSymbol, string)>() - .BeEmpty(); - } - - // ----------------------------------------------------- - - public static TheoryData GeneratorSources - => new TheoryData { - { - new string[] { - "TestData/Source/Range.cs", - "TestData/Source/Contains.ValueEnumerable.cs", - }, - new string[] { - } - }, - { - new string[] { - "TestData/Source/Select.ArraySegment.cs", - "TestData/Source/Contains.ValueEnumerable.cs", - }, - new string[] { - } - }, - { - new string[] { - "TestData/Source/Range.cs", - "TestData/Source/Count.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Range.Count.cs", - } - }, - { - new string[] { - "TestData/Source/Repeat.cs", - "TestData/Source/Count.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Repeat.Count.cs", - } - }, - { - new string[] { - "TestData/Source/Range.cs", - "TestData/Source/Where.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Range.Where.cs", - } - }, - { - new string[] { - "TestData/Source/Range.cs", - "TestData/Source/Select.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Range.Select.cs", - } - }, - { - new string[] { - "TestData/Source/Count.ValueEnumerable.cs", - "TestData/Source/Where.ArraySegment.cs", - }, - new string[] { - "TestData/Results/Where.ArraySegment.Count.cs", - } - }, - { - new string[] { - "TestData/Source/Any.ArraySegment.cs", - "TestData/Source/Any.ReadOnlyList.cs", - "TestData/Source/Any.ValueEnumerable.cs", - "TestData/Source/Any.ValueReadOnlyCollection.cs", - "TestData/Source/Where.ValueEnumerable.cs", - }, - new string[] { - } - }, - { - new string[] { - "TestData/Source/Any.ArraySegment.cs", - "TestData/Source/Any.ReadOnlyList.cs", - "TestData/Source/Any.ValueEnumerable.cs", - "TestData/Source/Any.ValueReadOnlyCollection.cs", - "TestData/Source/Select.ArraySegment.cs", - }, - new string[] { - "TestData/Results/Select.ArraySegment.Any.cs", - } - }, - { - new string[] { - "TestData/Source/Any.ArraySegment.cs", - "TestData/Source/Any.ReadOnlyList.cs", - "TestData/Source/Any.ValueEnumerable.cs", - "TestData/Source/Any.ValueReadOnlyCollection.cs", - "TestData/Source/Select.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Select.ValueEnumerable.Any.cs", - } - }, - { - new string[] { - "TestData/Source/Count.ValueEnumerable.cs", - "TestData/Source/Where.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Where.ValueEnumerable.Count.cs", - } - }, - { - new string[] { - "TestData/Source/First.ValueEnumerable.cs", - "TestData/Source/Where.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Where.ValueEnumerable.First.cs", - } - }, - { - new string[] { - "TestData/Source/First.ValueEnumerable.cs", - "TestData/Source/Select.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Select.ValueEnumerable.First.cs", - } - }, - { - new string[] { - "TestData/Source/Where.ValueEnumerable.cs", - "TestData/Source/Distinct.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Where.ValueEnumerable.Distinct.cs", - "TestData/Results/Distinct.ValueEnumerable.Where.cs", - } - }, - { - new string[] { - "TestData/Source/Where.ValueEnumerable.cs", - "TestData/Source/Select.ValueEnumerable.cs", - }, - new string[] { - "TestData/Results/Where.ValueEnumerable.Select.cs", - "TestData/Results/Select.ValueEnumerable.Where.cs", - } - }, - { - new string[] { - "TestData/Source/Where.ValueEnumerable.cs", - "TestData/Source/Dictionary.Bindings.cs", - }, - new string[] { - "TestData/Results/Dictionary.Where.cs", - } - }, - { - new string[] { - "TestData/Source/Select.ValueEnumerable.cs", - "TestData/Source/Dictionary.Bindings.cs", - }, - new string[] { - "TestData/Results/Dictionary.Select.cs", - } - }, - }; - - [Theory] - [MemberData(nameof(GeneratorSources))] - public async Task GenerateSourceShouldGenerate(string[] paths, string[] expected) - { - // Arrange - var generator = new OverloadsGenerator(); - var project = Verifier.CreateProject( - paths - .Concat(Directory.EnumerateFiles("TestData/Source/Common", "*.cs", SearchOption.AllDirectories)) - .Select(path => File.ReadAllText(path))); - var compilation = await project.GetCompilationAsync().ConfigureAwait(false); - - // Act - var extensionMethods = generator.CollectExtensionMethods(compilation!); - var result = generator.GenerateSource(compilation!, extensionMethods); - - // Assert - _ = result.Select(item => item.Source) - .ToArray() - .Must() - .BeEqualTo(expected.Select(path => File.ReadAllText(path))); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Dictionary.Select.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Dictionary.Select.cs deleted file mode 100644 index 4eda86132..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Dictionary.Select.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class DictionaryBindings - { - public partial struct ValueWrapper - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable, System.Collections.Generic.Dictionary.Enumerator, System.Collections.Generic.KeyValuePair, TResult, NetFabric.Hyperlinq.FunctionWrapper, TResult>> Select(System.Func, TResult> selector) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Select, System.Collections.Generic.Dictionary.Enumerator, System.Collections.Generic.KeyValuePair, TResult>(this, selector); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable, System.Collections.Generic.Dictionary.Enumerator, System.Collections.Generic.KeyValuePair, TResult, TSelector> Select(TSelector selector = default) - where TSelector : struct, NetFabric.Hyperlinq.IFunction, TResult> - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Select, System.Collections.Generic.Dictionary.Enumerator, System.Collections.Generic.KeyValuePair, TResult, TSelector>(this, selector); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Dictionary.Where.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Dictionary.Where.cs deleted file mode 100644 index e5aeeacaf..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Dictionary.Where.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class DictionaryBindings - { - public partial struct ValueWrapper - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable, System.Collections.Generic.Dictionary.Enumerator, System.Collections.Generic.KeyValuePair, NetFabric.Hyperlinq.FunctionWrapper, bool>> Where(System.Func, bool> predicate) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Where, System.Collections.Generic.Dictionary.Enumerator, System.Collections.Generic.KeyValuePair>(this, predicate); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable, System.Collections.Generic.Dictionary.Enumerator, System.Collections.Generic.KeyValuePair, TPredicate> Where(TPredicate predicate = default) - where TPredicate : struct, NetFabric.Hyperlinq.IFunction, bool> - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Where, System.Collections.Generic.Dictionary.Enumerator, System.Collections.Generic.KeyValuePair, TPredicate>(this, predicate); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Distinct.ValueEnumerable.Where.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Distinct.ValueEnumerable.Where.cs deleted file mode 100644 index 68d5bfe0d..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Distinct.ValueEnumerable.Where.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public partial struct DistinctEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable, NetFabric.Hyperlinq.ValueEnumerableExtensions.DistinctEnumerable.DisposableEnumerator, TSource, NetFabric.Hyperlinq.FunctionWrapper> Where(System.Func predicate) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Where, NetFabric.Hyperlinq.ValueEnumerableExtensions.DistinctEnumerable.DisposableEnumerator, TSource>(this, predicate); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable, NetFabric.Hyperlinq.ValueEnumerableExtensions.DistinctEnumerable.DisposableEnumerator, TSource, TPredicate> Where(TPredicate predicate = default) - where TPredicate : struct, NetFabric.Hyperlinq.IFunction - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Where, NetFabric.Hyperlinq.ValueEnumerableExtensions.DistinctEnumerable.DisposableEnumerator, TSource, TPredicate>(this, predicate); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.DistinctEnumerable, NetFabric.Hyperlinq.ValueEnumerableExtensions.DistinctEnumerable.DisposableEnumerator, TSource> Distinct() - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Distinct, NetFabric.Hyperlinq.ValueEnumerableExtensions.DistinctEnumerable.DisposableEnumerator, TSource>(this); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Range.Count.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Range.Count.cs deleted file mode 100644 index 73900248e..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Range.Count.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerable - { - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this NetFabric.Hyperlinq.ValueEnumerable.RangeEnumerable source) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Count(source); - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Range.Select.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Range.Select.cs deleted file mode 100644 index 09bf8358a..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Range.Select.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerable - { - public partial struct RangeEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable> Select(System.Func selector) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Select(this, selector); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable Select(TSelector selector = default) - where TSelector : struct, NetFabric.Hyperlinq.IFunction - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Select(this, selector); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Range.Where.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Range.Where.cs deleted file mode 100644 index 4b9a35905..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Range.Where.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerable - { - public partial struct RangeEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable> Where(System.Func predicate) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Where(this, predicate); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable Where(TPredicate predicate = default) - where TPredicate : struct, NetFabric.Hyperlinq.IFunction - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Where(this, predicate); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Repeat.Count.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Repeat.Count.cs deleted file mode 100644 index f31c15431..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Repeat.Count.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerable - { - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this NetFabric.Hyperlinq.ValueEnumerable.RepeatEnumerable source) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Count, NetFabric.Hyperlinq.ValueEnumerable.RepeatEnumerable.DisposableEnumerator, TSource>(source); - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ArraySegment.Any.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ArraySegment.Any.cs deleted file mode 100644 index 2a75b24f4..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ArraySegment.Any.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - public partial struct ArraySegmentSelectEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any(System.Func predicate) - => NetFabric.Hyperlinq.ReadOnlyListExtensions.Any, TResult>(this, predicate); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any(TPredicate predicate = default) - where TPredicate : struct, NetFabric.Hyperlinq.IFunction - => NetFabric.Hyperlinq.ReadOnlyListExtensions.Any, TResult, TPredicate>(this, predicate); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ValueEnumerable.Any.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ValueEnumerable.Any.cs deleted file mode 100644 index 0a6515ed3..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ValueEnumerable.Any.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public partial struct SelectEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any() - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Any, NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable.DisposableEnumerator, TResult>(this); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any(System.Func predicate) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Any, NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable.DisposableEnumerator, TResult>(this, predicate); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any(TPredicate predicate = default) - where TPredicate : struct, NetFabric.Hyperlinq.IFunction - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Any, NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable.DisposableEnumerator, TResult, TPredicate>(this, predicate); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ValueEnumerable.First.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ValueEnumerable.First.cs deleted file mode 100644 index 185d5728f..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ValueEnumerable.First.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public partial struct SelectEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.Option First() - => NetFabric.Hyperlinq.ValueEnumerableExtensions.First, NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable.DisposableEnumerator, TResult>(this); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ValueEnumerable.Where.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ValueEnumerable.Where.cs deleted file mode 100644 index 58b5dd28e..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Select.ValueEnumerable.Where.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public partial struct SelectEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable, NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable.DisposableEnumerator, TResult, NetFabric.Hyperlinq.FunctionWrapper> Where(System.Func predicate) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Where, NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable.DisposableEnumerator, TResult>(this, predicate); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable, NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable.DisposableEnumerator, TResult, TPredicate> Where(TPredicate predicate = default) - where TPredicate : struct, NetFabric.Hyperlinq.IFunction - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Where, NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable.DisposableEnumerator, TResult, TPredicate>(this, predicate); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ArraySegment.Count.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ArraySegment.Count.cs deleted file mode 100644 index 9dc5d6d80..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ArraySegment.Count.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - public partial struct ArraySegmentWhereEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Count, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentWhereEnumerable.DisposableEnumerator, TSource>(this); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.Count.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.Count.cs deleted file mode 100644 index 6b88fa161..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.Count.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public partial struct WhereEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Count, NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable.DisposableEnumerator, TSource>(this); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.Distinct.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.Distinct.cs deleted file mode 100644 index b76aac114..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.Distinct.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public partial struct WhereEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.DistinctEnumerable, NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable.DisposableEnumerator, TSource> Distinct() - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Distinct, NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable.DisposableEnumerator, TSource>(this); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.First.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.First.cs deleted file mode 100644 index 1a4283448..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.First.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public partial struct WhereEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.Option First() - => NetFabric.Hyperlinq.ValueEnumerableExtensions.First, NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable.DisposableEnumerator, TSource>(this); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.Select.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.Select.cs deleted file mode 100644 index 2bdd06674..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/Where.ValueEnumerable.Select.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public partial struct WhereEnumerable - { - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable, NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable.DisposableEnumerator, TSource, TResult, NetFabric.Hyperlinq.FunctionWrapper> Select(System.Func selector) - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Select, NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable.DisposableEnumerator, TSource, TResult>(this, selector); - - [GeneratedCode("NetFabric.Hyperlinq.SourceGenerator", "1.0.0")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NetFabric.Hyperlinq.ValueEnumerableExtensions.SelectEnumerable, NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable.DisposableEnumerator, TSource, TResult, TSelector> Select(TSelector selector = default) - where TSelector : struct, NetFabric.Hyperlinq.IFunction - => NetFabric.Hyperlinq.ValueEnumerableExtensions.Select, NetFabric.Hyperlinq.ValueEnumerableExtensions.WhereEnumerable.DisposableEnumerator, TSource, TResult, TSelector>(this, selector); - - } - - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ArraySegment.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ArraySegment.cs deleted file mode 100644 index fb6d8bcbb..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ArraySegment.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - public static bool Any(this in ArraySegment source) - => source.Count != 0; - - public static bool Any(this in ArraySegment source, Func predicate) - => source.Any(new FunctionWrapper(predicate)); - - public static bool Any(this in ArraySegment source, TPredicate predicate = default) - where TPredicate : struct, IFunction - => default; - } -} - diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ReadOnlyList.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ReadOnlyList.cs deleted file mode 100644 index 0c52c3dbf..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ReadOnlyList.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TList source) - where TList : struct, IReadOnlyList - => source.Count is not 0; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TList source, Func predicate) - where TList : struct, IReadOnlyList - => source.Any>(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TList source, TPredicate predicate = default) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => default; - } -} - diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ValueEnumerable.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ValueEnumerable.cs deleted file mode 100644 index 2c79e1b31..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Any.ValueEnumerable.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - - public static bool Any(this TEnumerable source) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => default; - - public static bool Any(this TEnumerable source, Func predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source.Any>(new FunctionWrapper(predicate)); - - public static bool Any(this TEnumerable source, TPredicate predicate = default) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => default; - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/GeneratorMappingAttribute.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/GeneratorMappingAttribute.cs deleted file mode 100644 index 662fc83f5..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/GeneratorMappingAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; - -namespace NetFabric.Hyperlinq -{ - [ExcludeFromCodeCoverage] - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method, AllowMultiple = true)] - public sealed class GeneratorMappingAttribute : Attribute - { - public string From { get; } - public string To { get; } - public bool IsConcreteType { get; } - - public GeneratorMappingAttribute(string from, string to, bool isConcreteType = false) - => (From, To, IsConcreteType) = (from, to , isConcreteType); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/IFunction.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/IFunction.cs deleted file mode 100644 index 719dbb63a..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/IFunction.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace NetFabric.Hyperlinq -{ - public interface IFunction - { - TResult Invoke(T arg); - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/IFunctionWrapper.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/IFunctionWrapper.cs deleted file mode 100644 index ce38a1db7..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/IFunctionWrapper.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace NetFabric.Hyperlinq -{ - public readonly struct FunctionWrapper - : IFunction - { - readonly Func function; - - public FunctionWrapper(Func function) - => this.function = function; - - public TResult Invoke(T arg) - => function(arg); - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/IValueEnumerable.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/IValueEnumerable.cs deleted file mode 100644 index d4efc695c..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/IValueEnumerable.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public interface IValueEnumerable - : IEnumerable - where TEnumerator - : struct - , IEnumerator - { - new TEnumerator GetEnumerator(); - } - - public interface IValueReadOnlyCollection - : IReadOnlyCollection - , IValueEnumerable - where TEnumerator - : struct - , IEnumerator - { - } - - public interface IValueReadOnlyList - : IReadOnlyList - , IValueReadOnlyCollection - where TEnumerator - : struct - , IEnumerator - { - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/Option.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/Option.cs deleted file mode 100644 index 4c68b37b2..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/Option.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public readonly struct Option - { - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/PredicateCombination.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/PredicateCombination.cs deleted file mode 100644 index 27b56347f..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/PredicateCombination.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace NetFabric.Hyperlinq -{ - public struct PredicateCombination - : IFunction - where TPredicate1 : struct, IFunction - where TPredicate2 : struct, IFunction - { - TPredicate1 first; - TPredicate2 second; - - public PredicateCombination(TPredicate1 first, TPredicate2 second) - => (this.first, this.second) = (first, second); - - public bool Invoke(TSource item) - => first.Invoke(item) && second.Invoke(item); - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/SelectorCombination.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/SelectorCombination.cs deleted file mode 100644 index f7dfe9134..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/SelectorCombination.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace NetFabric.Hyperlinq -{ - public readonly struct SelectorCombination - : IFunction - where TSelector1 : struct, IFunction - where TSelector2 : struct, IFunction - { - readonly TSelector1 first; - readonly TSelector2 second; - - public SelectorCombination(TSelector1 first, TSelector2 second) - => (this.first, this.second) = (first, second); - - public TResult Invoke(TSource item) - => second.Invoke(first.Invoke(item)); - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Contains.ValueEnumerable.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Contains.ValueEnumerable.cs deleted file mode 100644 index 7de29c2c4..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Contains.ValueEnumerable.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public static bool Contains(this TEnumerable source, TSource value) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => default; - - public static bool Contains(this TEnumerable source, TSource value, IEqualityComparer? comparer) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => default; - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Count.ValueEnumerable.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Count.ValueEnumerable.cs deleted file mode 100644 index 897fe92b1..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Count.ValueEnumerable.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public static int Count(this TEnumerable _) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => 0; - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Dictionary.Bindings.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Dictionary.Bindings.cs deleted file mode 100644 index bda5fd24c..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Dictionary.Bindings.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class DictionaryBindings - { - [GeneratorMapping("TSource", "System.Collections.Generic.KeyValuePair", true)] - public readonly partial struct ValueWrapper - : IValueReadOnlyCollection, Dictionary.Enumerator> - , ICollection> - where TKey : notnull - { - readonly Dictionary source; - - public ValueWrapper(Dictionary source) - => this.source = source; - - public readonly int Count - => source.Count; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Dictionary.Enumerator GetEnumerator() - => source.GetEnumerator(); - readonly IEnumerator> IEnumerable>.GetEnumerator() - => source.GetEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() - => source.GetEnumerator(); - - bool ICollection>.IsReadOnly - => true; - - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) - => ((ICollection>)source).CopyTo(array, arrayIndex); - - void ICollection>.Add(KeyValuePair item) - => throw new NotSupportedException(); - void ICollection>.Clear() - => throw new NotSupportedException(); - bool ICollection>.Contains(KeyValuePair item) - => throw new NotSupportedException(); - bool ICollection>.Remove(KeyValuePair item) - => throw new NotSupportedException(); - } - - public static int Count(this ValueWrapper source) - where TKey : notnull - => source.Count; - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Distinct.ArraySegment.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Distinct.ArraySegment.cs deleted file mode 100644 index 2e62b0118..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Distinct.ArraySegment.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - public static ArraySegmentDistinctEnumerable Distinct(this in ArraySegment source) - => new(source); - - public readonly partial struct ArraySegmentDistinctEnumerable - : IValueEnumerable.DisposableEnumerator> - { - readonly ArraySegment source; - - internal ArraySegmentDistinctEnumerable(in ArraySegment source) - => this.source = source; - - public readonly Enumerator GetEnumerator() - => new(); - readonly DisposableEnumerator IValueEnumerable.DisposableEnumerator>.GetEnumerator() - => new(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - - public struct Enumerator - { - } - - public struct DisposableEnumerator - : IEnumerator - { - public readonly TSource Current => default!; - readonly TSource IEnumerator.Current => default!; - readonly object IEnumerator.Current => default!; - - public bool MoveNext() - => false; - - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() { } - } - } - } -} - diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Distinct.ValueEnumerable.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Distinct.ValueEnumerable.cs deleted file mode 100644 index b13db620f..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Distinct.ValueEnumerable.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - public static DistinctEnumerable Distinct(this TEnumerable source) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => new(source); - - public readonly partial struct DistinctEnumerable - : IValueEnumerable.DisposableEnumerator> - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - { - readonly TEnumerable source; - - internal DistinctEnumerable(TEnumerable source) - => this.source = source; - - public readonly Enumerator GetEnumerator() - => new(); - readonly DisposableEnumerator IValueEnumerable.DisposableEnumerator>.GetEnumerator() - => new(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - - public struct Enumerator - { - } - - public struct DisposableEnumerator - : IEnumerator - { - public readonly TSource Current => default!; - readonly TSource IEnumerator.Current => default!; - readonly object IEnumerator.Current => default; - - public bool MoveNext() - => false; - - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() { } - } - } - } -} - diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/ExtensionMethods.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/ExtensionMethods.cs deleted file mode 100644 index 55bca4934..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/ExtensionMethods.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static class ExtensionMethods - { - public static void ExtensionMethod(this TEnumerable _) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - { } - } - -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/First.ValueEnumerable.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/First.ValueEnumerable.cs deleted file mode 100644 index 967f11668..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/First.ValueEnumerable.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - - public static Option First(this TEnumerable source) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => default; - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/NoExtensionMethods.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/NoExtensionMethods.cs deleted file mode 100644 index 2fa47b425..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/NoExtensionMethods.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public class NotStaticClass - { - } - - static class NotPublicStaticClass - { - public static void ExtensionMethod(this TEnumerable _) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - { } - } - - public static class NoExtensionMethods - { - public static void NotConstrainedExtensionMethod(this ArraySegment _) { } - - public static void NotExtensionMethod(TEnumerable _) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - { } - - static void NotPublicExtensionMethod(this TEnumerable _) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - { } - - [GeneratorIgnore] - public static void IgnoredExtensionMethod(this TEnumerable _) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - { } - } - -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Range.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Range.cs deleted file mode 100644 index f7be13ddb..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Range.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerable - { - public static RangeEnumerable Range(int start, int count) - => new(start, count); - - [GeneratorMapping("TSource", "int", true)] - public readonly partial struct RangeEnumerable - : IValueReadOnlyCollection - , ICollection - { - readonly int start; - readonly int end; - - internal RangeEnumerable(int start, int count) - { - this.start = start; - Count = count; - end = checked(start + count); - } - - public readonly int Count { get; } - - - public readonly Enumerator GetEnumerator() - => new(); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(int[] array, int arrayIndex) - { - } - - public bool Contains(int value) - => value >= start && value < end; - - void ICollection.Add(int item) - => throw new NotSupportedException(); - void ICollection.Clear() - => throw new NotSupportedException(); - bool ICollection.Remove(int item) - => throw new NotSupportedException(); - - public struct Enumerator - { - } - - public struct DisposableEnumerator - : IEnumerator - { - public readonly int Current => 0; - readonly int IEnumerator.Current => 0; - readonly object IEnumerator.Current => 0; - - public bool MoveNext() - => false; - - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() { } - } - - public bool Contains(int value, IEqualityComparer? comparer) - => default; - - public RangeEnumerable Skip(int count) - => default; - } - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Repeat.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Repeat.cs deleted file mode 100644 index e89ca1727..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Repeat.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerable - { - - public static RepeatEnumerable Repeat(TSource value, int count) - { - if (count < 0) throw new ArgumentOutOfRangeException(nameof(count)); - - return new RepeatEnumerable(value, count); - } - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct RepeatEnumerable - : IValueReadOnlyCollection.DisposableEnumerator> - , ICollection - { - readonly TSource value; - readonly int count; - - internal RepeatEnumerable(TSource value, int count) - { - this.value = value; - this.count = count; - } - - public readonly int Count - => count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(Span span) - { - - } - - public void CopyTo(TSource[] array, int arrayIndex) - { - - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource item) - => count is not 0 && EqualityComparer.Default.Equals(value, item); - - public int IndexOf(TSource item) - => count is not 0 && EqualityComparer.Default.Equals(value, item) - ? 0 - : -1; - - [ExcludeFromCodeCoverage] - void ICollection.Add(TSource item) - => throw new NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => throw new NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TSource item) - => throw new NotSupportedException(); - - [StructLayout(LayoutKind.Sequential)] - public struct Enumerator - { - int counter; - readonly int end; - - internal Enumerator(in RepeatEnumerable enumerable) - { - Current = enumerable.value; - counter = -1; - end = counter + enumerable.Count; - } - - public readonly TSource Current { get; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++counter <= end; - } - - [StructLayout(LayoutKind.Sequential)] - public struct DisposableEnumerator - : IEnumerator - { - int counter; - readonly int end; - - internal DisposableEnumerator(in RepeatEnumerable enumerable) - { - Current = enumerable.value; - counter = -1; - end = counter + enumerable.Count; - } - - public readonly TSource Current { get; } - readonly TSource IEnumerator.Current - => Current; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => Current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++counter <= end; - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => throw new NotSupportedException(); - - public readonly void Dispose() { } - } - } - } -} - diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Select.ArraySegment.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Select.ArraySegment.cs deleted file mode 100644 index 8f8a25337..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Select.ArraySegment.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - public static ArraySegmentSelectEnumerable> Select(this in ArraySegment source, Func selector) - => Select>(source, new FunctionWrapper(selector)); - - public static ArraySegmentSelectEnumerable Select(this in ArraySegment source, TSelector selector = default) - where TSelector : struct, IFunction - => new(source, selector); - - [GeneratorMapping("TSource", "TResult")] - public readonly partial struct ArraySegmentSelectEnumerable - : IValueReadOnlyList.DisposableEnumerator> - , IList - where TSelector : struct, IFunction - { - readonly ArraySegment source; - readonly TSelector selector; - - internal ArraySegmentSelectEnumerable(in ArraySegment source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - public readonly int Count - => 0; - - bool ICollection.IsReadOnly - => true; - - void ICollection.CopyTo(TResult[] array, int arrayIndex) - { } - void ICollection.Add(TResult item) - => throw new NotSupportedException(); - void ICollection.Clear() - => throw new NotSupportedException(); - public bool Contains(TResult item) - => default; - bool ICollection.Remove(TResult item) - => throw new NotSupportedException(); - int IList.IndexOf(TResult item) - => default; - void IList.Insert(int index, TResult item) - => throw new NotSupportedException(); - void IList.RemoveAt(int index) - => throw new NotSupportedException(); - - public readonly TResult this[int index] - => default!; - TResult IReadOnlyList.this[int index] - => this[index]; - TResult IList.this[int index] - { - get => this[index]!; - set => throw new NotSupportedException(); - } - - public readonly Enumerator GetEnumerator() - => new(); - readonly DisposableEnumerator IValueEnumerable.DisposableEnumerator>.GetEnumerator() - => new(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - - public struct Enumerator - { - } - - public struct DisposableEnumerator - : IEnumerator - { - public readonly TResult Current => default!; - readonly TResult IEnumerator.Current => default!; - readonly object IEnumerator.Current => default!; - - public bool MoveNext() - => false; - - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() { } - } - - public bool Any() - => source.Count is not 0; - - public bool Contains(TResult value, IEqualityComparer? comparer = default) - => default; - - public ArraySegmentSelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select, TResult2>(new FunctionWrapper(selector)); - - public ArraySegmentSelectEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => Select>(source, new SelectorCombination(this.selector, selector)); - } - - public static int Count(this ArraySegmentSelectEnumerable source) - where TSelector : struct, IFunction - => 0; - } -} - diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Select.ValueEnumerable.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Select.ValueEnumerable.cs deleted file mode 100644 index eedd76337..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Select.ValueEnumerable.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - public static SelectEnumerable> Select(this TEnumerable source, Func selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => Select>(source, new FunctionWrapper(selector)); - - public static SelectEnumerable Select(this TEnumerable source, TSelector selector = default) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => new(source, selector); - - [GeneratorMapping("TSource", "TResult")] - public readonly partial struct SelectEnumerable - : IValueEnumerable.DisposableEnumerator> - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - readonly TEnumerable source; - readonly TSelector selector; - - internal SelectEnumerable(TEnumerable source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - public readonly Enumerator GetEnumerator() - => new(); - readonly DisposableEnumerator IValueEnumerable.DisposableEnumerator>.GetEnumerator() - => new(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - - public struct Enumerator - { - } - - public struct DisposableEnumerator - : IEnumerator - { - public readonly TResult Current => default!; - readonly TResult IEnumerator.Current => default!; - readonly object IEnumerator.Current => default!; - - public bool MoveNext() - => false; - - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() { } - } - - public int Count() - => source.Count(); - - public SelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select, TResult2>(new FunctionWrapper(selector)); - - public SelectEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => Select>(source, new SelectorCombination(this.selector, selector)); - } - } -} - diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/ToDictionary.ArraySegment.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/ToDictionary.ArraySegment.cs deleted file mode 100644 index da24d7b1b..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/ToDictionary.ArraySegment.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this in ArraySegment source, Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - { - if (keySelector is null) throw new ArgumentNullException(nameof(keySelector)); - - return ToDictionary>(source, new FunctionWrapper(keySelector), comparer); - } - - public static Dictionary ToDictionary(this in ArraySegment source, TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - { - var dictionary = new Dictionary(source.Count, comparer); - return dictionary; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this in ArraySegment source, Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - { - if (keySelector is null) throw new ArgumentNullException(nameof(keySelector)); - if (elementSelector is null) throw new ArgumentNullException(nameof(elementSelector)); - - return ToDictionary, FunctionWrapper>(source, new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - } - - public static Dictionary ToDictionary(this in ArraySegment source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - { - var dictionary = new Dictionary(source.Count, comparer); - return dictionary; - } - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Where.ArraySegment.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Where.ArraySegment.cs deleted file mode 100644 index 412d7ea1c..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Where.ArraySegment.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - public static ArraySegmentWhereEnumerable> Where(this in ArraySegment source, Func predicate) - => Where(source, new FunctionWrapper(predicate)); - - public static ArraySegmentWhereEnumerable Where(this in ArraySegment source, TPredicate predicate = default) - where TPredicate : struct, IFunction - => new(source, predicate); - - public readonly partial struct ArraySegmentWhereEnumerable - : IValueEnumerable.DisposableEnumerator> - where TPredicate : struct, IFunction - { - readonly ArraySegment source; - readonly TPredicate predicate; - - internal ArraySegmentWhereEnumerable(in ArraySegment source, TPredicate predicate) - => (this.source, this.predicate) = (source, predicate); - - public readonly Enumerator GetEnumerator() - => new(); - readonly DisposableEnumerator IValueEnumerable.DisposableEnumerator>.GetEnumerator() - => new(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() - => new DisposableEnumerator(); - - public struct Enumerator - { - } - - public struct DisposableEnumerator - : IEnumerator - { - public readonly TSource Current => default!; - readonly TSource IEnumerator.Current => default!; - readonly object IEnumerator.Current => default; - - public bool MoveNext() - => false; - - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() { } - } - - public bool Any() - => source.Any(predicate); - - public static bool Any(Func predicate) - => default; - - public static bool Any(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => default; - - public ArraySegmentWhereEnumerable, TSource>> Where(Func predicate) - => Where(new FunctionWrapper(predicate)); - - public ArraySegmentWhereEnumerable> Where(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => Where>(source, new PredicateCombination(this.predicate, predicate)); - } - } -} - diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Where.ValueEnumerable.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Where.ValueEnumerable.cs deleted file mode 100644 index 276648358..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Where.ValueEnumerable.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - public static WhereEnumerable> Where(this TEnumerable source, Func predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => Where>(source, new FunctionWrapper(predicate)); - - public static WhereEnumerable Where(this TEnumerable source, TPredicate predicate = default) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => new(source, predicate); - - public readonly partial struct WhereEnumerable - : IValueEnumerable.DisposableEnumerator> - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - { - readonly TEnumerable source; - readonly TPredicate predicate; - - internal WhereEnumerable(TEnumerable source, TPredicate predicate) - => (this.source, this.predicate) = (source, predicate); - - public readonly Enumerator GetEnumerator() - => new(); - readonly DisposableEnumerator IValueEnumerable.DisposableEnumerator>.GetEnumerator() - => new(); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(); - - public struct Enumerator - { - } - - public struct DisposableEnumerator - : IEnumerator - { - public readonly TSource Current => default!; - readonly TSource IEnumerator.Current => default!; - readonly object IEnumerator.Current => default; - - public bool MoveNext() - => false; - - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() { } - } - - public bool Any() - => source.Any(predicate); - - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - public bool Any(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => source.Any>(new PredicateCombination(this.predicate, predicate)); - - public WhereEnumerable, TSource>> Where(Func predicate) - => Where(new FunctionWrapper(predicate)); - - public WhereEnumerable> Where(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => Where>(source, new PredicateCombination(this.predicate, predicate)); - } - } -} - diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/Verifier.cs b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/Verifier.cs deleted file mode 100644 index 1598e66b1..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/Verifier.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Text; -using System.Collections.Generic; -using System.Linq; - -namespace NetFabric.Hyperlinq.SourceGenerator.UnitTests -{ - class Verifier - { - static readonly MetadataReference CorlibReference = MetadataReference.CreateFromFile(typeof(object).Assembly.Location); - static readonly MetadataReference SystemCoreReference = MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location); - static readonly MetadataReference CSharpSymbolsReference = MetadataReference.CreateFromFile(typeof(CSharpCompilation).Assembly.Location); - static readonly MetadataReference CodeAnalysisReference = MetadataReference.CreateFromFile(typeof(Compilation).Assembly.Location); - - static string DefaultFilePathPrefix = "Test"; - static string TestProjectName = "TestProject"; - - public static Project CreateProject(IEnumerable sources) - { - var projectId = ProjectId.CreateNewId(debugName: TestProjectName); - - var solution = new AdhocWorkspace() - .CurrentSolution - .AddProject(projectId, TestProjectName, TestProjectName, LanguageNames.CSharp) - .AddMetadataReference(projectId, CorlibReference) - .AddMetadataReference(projectId, SystemCoreReference) - .AddMetadataReference(projectId, CSharpSymbolsReference) - .AddMetadataReference(projectId, CodeAnalysisReference); - - var count = 0; - foreach (var source in sources) - { - var newFileName = DefaultFilePathPrefix + count + ".cs"; - var documentId = DocumentId.CreateNewId(projectId, debugName: newFileName); - solution = solution.AddDocument(documentId, newFileName, SourceText.From(source)); - count++; - } - return solution.GetProject(projectId)!; - } - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator/NetFabric.Hyperlinq.SourceGenerator.csproj b/NetFabric.Hyperlinq.SourceGenerator/NetFabric.Hyperlinq.SourceGenerator.csproj deleted file mode 100644 index 986ef8b40..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator/NetFabric.Hyperlinq.SourceGenerator.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - netstandard2.0 - preview - enable - true - - - - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json ;$(RestoreAdditionalProjectSources) - - - - - - - - diff --git a/NetFabric.Hyperlinq.SourceGenerator/OverloadsGenerator.cs b/NetFabric.Hyperlinq.SourceGenerator/OverloadsGenerator.cs deleted file mode 100644 index 692379f88..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator/OverloadsGenerator.cs +++ /dev/null @@ -1,350 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Text; -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; - -namespace NetFabric.Hyperlinq.SourceGenerator -{ - [Generator] - public class OverloadsGenerator: ISourceGenerator - { - static readonly DiagnosticDescriptor unhandledExceptionError = new( - id: "HPLG001", - title: "Unhandled exception while generating oveloads", - messageFormat: "Unhandled exception while generating oveloads: {0}", - category: "OverloadsGenerator", - DiagnosticSeverity.Error, - isEnabledByDefault: true); - - public void Initialize(GeneratorInitializationContext context) - { - } - - public void Execute(GeneratorExecutionContext context) - { - //_ = Debugger.Launch(); // uncomment to debug this source generator - - try - { - var collectedExtensionMethods = CollectExtensionMethods(context.Compilation); - - var generatedSources = GenerateSource(context.Compilation, collectedExtensionMethods); - foreach ((var containerClass, var extendingType, var generatedSource) in generatedSources) - { - var hitName = $"{containerClass.OriginalDefinition.MetadataName}.{extendingType.OriginalDefinition.MetadataName}.g.cs"; - hitName = hitName.Replace('`', '.'); - context.AddSource(hitName, SourceText.From(generatedSource, Encoding.UTF8)); - } - - } - catch (Exception ex) - { - context.ReportDiagnostic(Diagnostic.Create(unhandledExceptionError, Location.None, ex.Message)); - } - } - - /// - /// Collects all the extension methods defined - /// - /// - /// A dictionary containing collections of the extension methods per type extended. - internal ImmutableDictionary> CollectExtensionMethods(Compilation compilation) - { - var result = ImmutableDictionary.CreateBuilder>(); - - // go through all implemented static types and get all the extension methods implemented - var extensionMethods = compilation.SourceModule.GlobalNamespace - .GetAllTypes() - .Where(typeSymbol => - typeSymbol.IsStatic - && typeSymbol.IsPublic()) - .SelectMany(typeSymbol => - typeSymbol.GetMembers() - .OfType() - .Where(methodSymbol => - methodSymbol.IsExtensionMethod - && methodSymbol.IsPublic() - && !methodSymbol.ShouldIgnore(compilation))); - - // go through all extension methods and store the ones where the extended type is a constrained generic parameter - foreach (var extensionMethod in extensionMethods) - { - var extensionType = extensionMethod.Parameters[0].Type; - var generic = extensionMethod.TypeParameters - .FirstOrDefault(typeParameter - => typeParameter.ConstraintTypes.Length > 0 - && typeParameter.Name == extensionType.Name); - if (generic is not null) - { - var extendingType = generic.ConstraintTypes[0]; // assume it's the first constraint - var key = extendingType.OriginalDefinition.MetadataName; - if (!result.TryGetValue(key, out var list)) - { - list = new List(); - result.Add(key, list); - } - var info = extensionMethod.GetInfo(compilation, 1); - list.Add(info); - } - } - - return result.ToImmutable(); - } - - /// - /// Generates the source for the overloads based on the defined extension methods. - /// - /// - /// A dictionary containing the defined extension methods. - /// The path where to serialize the generated code for debugging. - internal IEnumerable<(INamedTypeSymbol ContainerClass, INamedTypeSymbol ExtendedType, string Source)> GenerateSource(Compilation compilation, ImmutableDictionary> collectedExtensionMethods) - { - // cache a GeneratedCodeAttribute string to use on all generated methods - var generatorAssembly = GetType().Assembly; - var generatorAssemblyName = generatorAssembly.GetName().Name; - var generatorAssemblyVersion = AttributeExtensions.GetCustomAttribute(generatorAssembly)?.InformationalVersion ?? string.Empty; - var generatedCodeAttribute = $"[GeneratedCode(\"{generatorAssemblyName}\", \"{generatorAssemblyVersion}\")]"; - - // go through all candidate types to be extended - // these are inner types of a public static class that are not static and not interfaces - foreach (var extendingType in compilation.SourceModule.GlobalNamespace - .GetAllTypes() - .Where(type => type.IsStatic && type.IsReferenceType && type.IsPublic() && !type.ShouldIgnore(compilation)) - .SelectMany(containerType => containerType.GetTypeMembers().OfType() - .Where(type => !(type.IsStatic || type.IsInterface() || type.ShouldIgnore(compilation))))) - { - // check if it's a value enumerable and keep a reference to the implemented interface - var valueEnumerableInterface = extendingType.GetAllInterfaces() - .FirstOrDefault(@interface => @interface.Name is "IValueEnumerable" or "IAsyncValueEnumerable"); - if (valueEnumerableInterface is null) - continue; - - // get the types of the enumerable, enumerator and source from the generic parameters declaration - var enumerableType = extendingType; - var enumeratorType = valueEnumerableInterface.TypeArguments[1]; - var sourceType = valueEnumerableInterface.TypeArguments[0]; - - // get the type mappings from the GeneratorMappingsAttribute, if found. - var typeGenericsMapping = extendingType.GetGenericsMappings(compilation); - - // get the info of all the instance methods declared in the type to be extended - var implementedInstanceMethods = extendingType.GetMembers().OfType() - .Where(method => method.Name is not ".ctor") // ignore the constructors - .Select(method => method.GetInfo(compilation)) - .ToArray(); - - // get the extension methods for this type declared in the outter static type - var implementedExtensionMethods = extendingType.ContainingType.GetMembers().OfType() - .Where(method - => method.IsExtensionMethod - && method.Parameters[0].Type.ToDisplayString() == extendingType.ToDisplayString()) - .Select(method => method.GetInfo(compilation, 1)) - .ToArray(); - - // join the two lists together as these are the implemented methods for this type - var implementedMethods = implementedInstanceMethods.Concat(implementedExtensionMethods) - .ToList(); - - // lists of methods to be generated - var instanceMethodsToBeGenerated = new List(); - var extensionMethodsToBeGenerated = new List(); - - // go through all the implemented interfaces so that - // the overloads are generated based on the extension methods defined for these - var extendingTypeInterfaces = extendingType.AllInterfaces; - for (var interfaceIndex = 0; interfaceIndex < extendingTypeInterfaces.Length; interfaceIndex++) - { - var extendingTypeInterface = extendingTypeInterfaces[interfaceIndex]; - - // get the extension methods collected for this interface - if (!collectedExtensionMethods.TryGetValue(extendingTypeInterface.OriginalDefinition.MetadataName, out var overloadingMethods)) - continue; - - // check which ones should be generated - // the method can be already defined by a more performant custom implementation - for (var methodIndex = 0; methodIndex < overloadingMethods.Count; methodIndex++) - { - var overloadingMethod = overloadingMethods[methodIndex]; - - // check if already implemented - var mappedOverloadingMethods = overloadingMethod.ApplyMappings(typeGenericsMapping); - if (!implementedMethods.Any(method => method.IsOverload(mappedOverloadingMethods)) - && !((mappedOverloadingMethods.Name is "Select" || mappedOverloadingMethods.Name is "SelectAt") && (extendingType.Name.EndsWith("SelectEnumerable") || extendingType.Name.EndsWith("SelectAtEnumerable")))) // these cases are hard to fix other way - { - // check if there's a collision with a property - if (extendingType.GetMembers().OfType() - .Any(property => property.Name == mappedOverloadingMethods.Name)) - { - // this method will be generated as an extension method - extensionMethodsToBeGenerated.Add(mappedOverloadingMethods); - } - else - { - // this method will generated as an instance method - instanceMethodsToBeGenerated.Add(mappedOverloadingMethods); - } - - implementedMethods.Add(mappedOverloadingMethods); - } - } - } - - // generate the code for the instance methods and extension methods, if any... - if (instanceMethodsToBeGenerated.Count is not 0 || extensionMethodsToBeGenerated.Count is not 0) - { - var builder = new CodeBuilder(); - _ = builder - .AppendLine("using System;") - .AppendLine("using System.CodeDom.Compiler;") - .AppendLine("using System.Diagnostics;") - .AppendLine("using System.Runtime.CompilerServices;") - .AppendLine(); - - using (builder.AppendBlock($"namespace NetFabric.Hyperlinq")) - { - // the generator extends the types by adding partial types - // both the outter and the inner types have to be declared as partial - using (builder.AppendBlock($"public static partial class {extendingType.ContainingType.Name}")) - { - // generate the instance methods in the inner type - if (instanceMethodsToBeGenerated.Count is not 0) - { - var extendingTypeGenericParameters = string.Empty; - if (extendingType.IsGenericType) - { - var parametersDefinition = new StringBuilder(); - _ = parametersDefinition.Append($"<{extendingType.TypeParameters.Select(parameter => parameter.ToDisplayString()).ToCommaSeparated()}>"); - // foreach (var typeParameter in extendingType.TypeParameters.Where(typeParameter => typeParameter.ConstraintTypes.Length is not 0)) - // _ = parametersDefinition.Append($" where {typeParameter.Name} : {typeParameter.AsConstraintsStrings().ToCommaSeparated()}"); - extendingTypeGenericParameters = parametersDefinition.ToString(); - } - - var entity = extendingType.IsValueType - ? "struct" - : "class"; - using (builder.AppendBlock($"public partial {entity} {extendingType.Name}{extendingTypeGenericParameters}")) - { - foreach (var instanceMethod in instanceMethodsToBeGenerated) - { - var methodGenericsMapping = typeGenericsMapping.AddRange(instanceMethod.GenericsMapping); - GenerateMethodSource(builder, extendingType, instanceMethod, enumerableType, enumeratorType, sourceType, generatedCodeAttribute, methodGenericsMapping, false); - } - } - } - _ = builder.AppendLine(); - - // generate the extension methods in the outter type - foreach (var extensionMethod in extensionMethodsToBeGenerated) - { - var methodGenericsMapping = typeGenericsMapping.AddRange(extensionMethod.GenericsMapping); - GenerateMethodSource(builder, extendingType, extensionMethod, enumerableType, enumeratorType, sourceType, generatedCodeAttribute, methodGenericsMapping, true); - } - } - } - - var source = builder.ToString().Replace("TResult, TResult", "TSource, TResult"); - yield return (extendingType.ContainingType, extendingType, source); - } - } - } - - void GenerateMethodSource(CodeBuilder builder, INamedTypeSymbol extendingType, MethodInfo methodToGenerate, ITypeSymbol enumerableType, ITypeSymbol enumeratorType, ITypeSymbol sourceType, string generatedCodeAttribute, ImmutableArray<(string, string, bool)> genericsMapping, bool isExtensionMethod) - { - var extendingTypeTypeArguments = extendingType.MappedTypeArguments(genericsMapping) - .ToArray(); - var typeParameters = isExtensionMethod - ? methodToGenerate.TypeParameters - .Where(typeParameter => - !typeParameter.IsConcreteType - && typeParameter.Name is not "TEnumerable" and not "TEnumerator" and not "TList") - .ToArray() - : methodToGenerate.TypeParameters - .Where(typeParameter => - !typeParameter.IsConcreteType - && typeParameter.Name is not "TEnumerable" and not "TEnumerator" and not "TList" - && !extendingTypeTypeArguments.Any(argument => argument.Name == typeParameter.Name)) - .ToArray(); - - var methodReturnType = methodToGenerate.ReturnType.ToDisplayString(); - var genericsIndex = methodReturnType.IndexOf('<'); - if (genericsIndex >= 0) - { - methodReturnType = methodReturnType.Substring(0, genericsIndex); - if (methodToGenerate.ReturnType is INamedTypeSymbol namedMethodReturnType) - { - methodReturnType += MapTypeProperties(namedMethodReturnType.TypeArguments.Select(argument => argument.ToDisplayString()), enumerableType, enumeratorType, sourceType, genericsMapping); - } - } - if (methodReturnType is "TEnumerable") - methodReturnType = extendingType.ToDisplayString(); - - var methodName = methodToGenerate.Name; - var methodExtensionType = extendingType.ToDisplayString(); - var methodParameters = methodToGenerate.Parameters - .Select(parameter => parameter.DefaultValue is null - ? $"{parameter.Type} {parameter.Name}" - : $"{parameter.Type} {parameter.Name} = {parameter.DefaultValue}") - .ToCommaSeparated(); - var methodGenericParameters = typeParameters - .Select(typeParameter => typeParameter.Name) - .ToCommaSeparated(); - var methodGenericParametersString = methodGenericParameters.Any() - ? $"<{methodGenericParameters}>" - : string.Empty; - - var returnKeyword = string.Empty; - var callContainingType = methodToGenerate.ContainingType; - var callTypeParameters = MapTypeProperties(methodToGenerate.TypeParameters.Select(parameter => parameter.Name), enumerableType, enumeratorType, sourceType, genericsMapping); - var callParameters = methodToGenerate.Parameters.Select(parameter => parameter.Name).ToCommaSeparated(); - - // generate the source - _ = builder - .AppendLine(generatedCodeAttribute) - //.AppendLine("[DebuggerNonUserCode]") - .AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]"); - if (isExtensionMethod) - { - callParameters = string.IsNullOrEmpty(callParameters) - ? "source" - : $"source, {callParameters}"; - - _ = builder.AppendLine($"public static {methodReturnType} {methodName}{methodGenericParametersString}(this {methodExtensionType} source{methodParameters})"); - } - else - { - callParameters = string.IsNullOrEmpty(callParameters) - ? "this" - : $"this, {callParameters}"; - - var methodReadonly = extendingType.IsValueType ? "readonly" : string.Empty; - _ = builder.AppendLine($"public {methodReadonly} {methodReturnType} {methodName}{methodGenericParametersString}({methodParameters})"); - } - foreach (var (name, constraints, _) in typeParameters.Where(typeParameter => typeParameter.Constraints.Any())) - _ = builder.AppendLine($"where {name} : {constraints}"); - - _ = builder - .AppendLine($"=> {callContainingType}.{methodName}{callTypeParameters}({callParameters});") - .AppendLine(); - } - - string MapTypeProperties(IEnumerable typePropertyNames, ITypeSymbol enumerableType, ITypeSymbol enumeratorType, ITypeSymbol sourceType, ImmutableArray<(string, string, bool)> genericsMapping) - { - var str = typePropertyNames.Select(typePropertyName => typePropertyName switch - { - "TEnumerable" or "TList" => enumerableType.ToDisplayString(genericsMapping), - "TEnumerator" => enumeratorType.ToDisplayString(genericsMapping), - "TSource" => sourceType.ToDisplayString(genericsMapping), - _ => typePropertyName.ApplyMappings(genericsMapping, out _), - }) - .ToCommaSeparated(); - - return string.IsNullOrEmpty(str) ? string.Empty : $"<{str}>"; - } - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator/Properties/AssemblyInfo.cs b/NetFabric.Hyperlinq.SourceGenerator/Properties/AssemblyInfo.cs deleted file mode 100644 index 423b8e090..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("NetFabric.Hyperlinq.SourceGenerator.UnitTests")] \ No newline at end of file diff --git a/NetFabric.Hyperlinq.SourceGenerator/Utils/CodeBuilder.cs b/NetFabric.Hyperlinq.SourceGenerator/Utils/CodeBuilder.cs deleted file mode 100644 index 1c57c05b2..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator/Utils/CodeBuilder.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Text; - -namespace NetFabric.Hyperlinq.SourceGenerator -{ - class CodeBuilder - { - static readonly string tab = " "; - - readonly StringBuilder builder = new(); - int currentLevel = 0; - - StringBuilder AppendIndentation() - { - for (var level = 0; level < currentLevel; level++) - _ = builder.Append(tab); - - return builder; - } - - public CodeBuilder AppendLine() - { - _ = builder.AppendLine(); - return this; - } - - public CodeBuilder AppendLine(char line) - { - _ = AppendIndentation().Append(line).AppendLine(); - return this; - } - - public CodeBuilder AppendLine(string line) - { - _ = AppendIndentation().AppendLine(line); - return this; - } - - public CodeBuilder AppendLine(Action line) - { - _ = AppendIndentation(); - line(builder); - _ = AppendLine(); - return this; - } - - public IDisposable AppendBlock(string line) - { - _ = AppendLine(line).AppendLine('{'); - currentLevel++; - return new CloseBlock(this); - } - - class CloseBlock : IDisposable - { - readonly CodeBuilder builder; - - public CloseBlock(CodeBuilder builder) - => this.builder = builder; - - public void Dispose() - { - builder.currentLevel--; - _ = builder.AppendLine('}'); - } - } - - public override string ToString() - => builder.ToString(); - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator/Utils/StringExtensions.cs b/NetFabric.Hyperlinq.SourceGenerator/Utils/StringExtensions.cs deleted file mode 100644 index dea43c04a..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator/Utils/StringExtensions.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Text; - -namespace NetFabric.Hyperlinq.SourceGenerator -{ - static class StringExtensions - { - public static string ToCommaSeparated(this string[] strings) - => string.Join(", ", strings); - - public static string ToCommaSeparated(this IEnumerable strings) - => string.Join(", ", strings); - - public static string ToCommaSeparated(this IReadOnlyList strings) - => strings.Count switch - { - 0 => string.Empty, - 1 => strings[0], - _ => AppendCommaSeparated(new StringBuilder(), strings).ToString(), - }; - - public static StringBuilder AppendCommaSeparated(this StringBuilder builder, IReadOnlyList strings) - => strings.Count switch - { - 0 => builder, - 1 => builder.Append(strings[0]), - _ => PerformAppendCommaSeparated(builder, strings), - }; - - static StringBuilder PerformAppendCommaSeparated(this StringBuilder builder, IReadOnlyList strings) - { - _ = builder.Append(strings[0]); - for (var index = 1; index < strings.Count; index++) - { - _ = builder.Append(", ").Append(strings[index]); - } - return builder; - } - - public static string ApplyMappings(this string value, ImmutableArray<(string, string, bool)> genericsMapping, out bool isConcreteType) - { - var result = value; - isConcreteType = false; - if (!genericsMapping.IsDefault) - { - foreach (var (from, to, isConcreteType2) in genericsMapping.Reverse()) - { - if (value == from && isConcreteType2) - { - isConcreteType = true; - return value.Replace(from, to); - } - result = result.Replace(from, to); - } - } - return result; - } - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator/Utils/SymbolExtensions.cs b/NetFabric.Hyperlinq.SourceGenerator/Utils/SymbolExtensions.cs deleted file mode 100644 index db0483322..000000000 --- a/NetFabric.Hyperlinq.SourceGenerator/Utils/SymbolExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.CodeAnalysis; -using System.Linq; - -namespace NetFabric.Hyperlinq.SourceGenerator -{ - static class SymbolExtensions - { - public static bool IsPublic(this ISymbol typeSymbol) - => typeSymbol.DeclaredAccessibility == Accessibility.Public; - - public static bool ShouldIgnore(this ISymbol symbol, Compilation compilation) - { - var attributeSymbol = compilation.GetTypeByMetadataName("NetFabric.Hyperlinq.GeneratorIgnoreAttribute"); - if (attributeSymbol is null) - return false; - var attribute = symbol.GetAttribute(attributeSymbol); - return attribute is not null - && (bool)attribute.ConstructorArguments[0].Value!; - } - - public static AttributeData? GetAttribute(this ISymbol property, INamedTypeSymbol attributeClassSymbol) - => property.GetAttributes() - .FirstOrDefault(attribute - => SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, attributeClassSymbol)); - - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.Array.Tests.cs deleted file mode 100644 index d63b48434..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.Array.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Count -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Count_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = source - .Count(); - - // Act - var result = source.AsValueEnumerable() - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ArraySegment.Tests.cs deleted file mode 100644 index 401403a5f..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ArraySegment.Tests.cs +++ /dev/null @@ -1,97 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Count -{ - public class ArraySegmentTests - { - [Fact] - public void Count_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - - // Act - var result = source.AsValueEnumerable() - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(0); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Count_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Count(wrapped); - - // Act - var result = wrapped.AsValueEnumerable() - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void Count_Predicate_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Count(predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void Count_PredicateAt_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Count(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ReadOnlyList.Tests.cs deleted file mode 100644 index 05af30d92..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,84 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Count -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Count_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Count(source); - - // Act - var result = wrapped - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void Count_Predicate_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Count(predicate); - - // Act - var result = wrapped - .Skip(skip) - .Take(take) - .Where(predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void Count_PredicateAt_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Count(); - - // Act - var result = wrapped - .Skip(skip) - .Take(take) - .Where(predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ReadOnlyMemory.Tests.cs deleted file mode 100644 index d823342a3..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,70 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Count -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Count_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .Count(source); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Count_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Count(source, predicate); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Count_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Count(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ReadOnlySpan.Tests.cs deleted file mode 100644 index ed0caabc6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,71 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Count -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Count_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .Count(source); - - // Act - var result = ArrayExtensions - .Count((ReadOnlySpan)source.AsSpan()); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Count_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Count(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Count_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Count(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.Span.Tests.cs deleted file mode 100644 index 6340538cd..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Count/Count.Span.Tests.cs +++ /dev/null @@ -1,70 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Count -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Count_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .Count(source); - - // Act - var result = ArrayExtensions - .Count(source.AsSpan()); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Count_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Count(source, predicate); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Count_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Count(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Sum/Sum.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Aggregation/Sum/Sum.Array.Tests.cs deleted file mode 100644 index bfa15a431..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Sum/Sum.Array.Tests.cs +++ /dev/null @@ -1,66 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum -{ - public class ArrayTests - { - public static TheoryData Sum => - new TheoryData - { - { new int[] { 1, 2, 3, 4, 5, 6, 7 } }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8 } }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 } }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 } }, - }; - - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - [MemberData(nameof(Sum))] - public void Sum_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .Sum(source); - - // Act - var result = source.AsValueEnumerable() - .Sum(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - public static TheoryData NullableSum => - new TheoryData - { - { new int?[] { null } }, - { new int?[] { null, null, null } }, - { new int?[] { null, 2, 3, 4, null } }, - { new int?[] { 1, 2, null, 4, 5 } }, - }; - - [Theory] - [MemberData(nameof(NullableSum))] - public void Sum_With_Nullable_ValidData_Must_Succeed(int?[] source) - { - // Arrange - var expected = Enumerable - .Sum(source); - - // Act - var result = source.AsValueEnumerable() - .Sum(); - - // Assert - _ = result.Must() - .BeEqualTo(expected.Value); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Sum/Sum.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Aggregation/Sum/Sum.ReadOnlyList.Tests.cs deleted file mode 100644 index 10583cbbc..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Sum/Sum.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum -{ - public class ReadOnlyListTests - { - public static TheoryData Sum => - new TheoryData - { - { new int[] { 1, 2, 3, 4, 5, 6, 7 } }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8 } }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 } }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 } }, - }; - - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - [MemberData(nameof(Sum))] - public void Sum_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap.AsList(source); - var expected = Enumerable - .Sum(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Sum(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - public static TheoryData NullableSum => - new TheoryData - { - { new int?[] { null } }, - { new int?[] { null, null, null } }, - { new int?[] { null, 2, 3, 4, null } }, - { new int?[] { 1, 2, null, 4, 5 } }, - }; - - [Theory] - [MemberData(nameof(NullableSum))] - public void Sum_With_Nullable_ValidData_Must_Succeed(int?[] source) - { - // Arrange - var wrapped = Wrap.AsList(source); - var expected = Enumerable - .Sum(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Sum(); - - // Assert - _ = result.Must() - .BeEqualTo(expected.Value); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Aggregation/Sum/Sum.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Aggregation/Sum/Sum.ValueEnumerable.Tests.cs deleted file mode 100644 index 080b7a0b0..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Aggregation/Sum/Sum.ValueEnumerable.Tests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum -{ - public class ValueEnumerableTests - { - public static TheoryData Sum => - new TheoryData - { - { new int[] { 1, 2, 3, 4, 5, 6, 7 } }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8 } }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 } }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 } }, - }; - - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - [MemberData(nameof(Sum))] - public void Sum_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap.AsValueEnumerable(source); - var expected = Enumerable - .Sum(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Sum(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - public static TheoryData NullableSum => - new TheoryData - { - { new int?[] { null } }, - { new int?[] { null, null, null } }, - { new int?[] { null, 2, 3, 4, null } }, - { new int?[] { 1, 2, null, 4, 5 } }, - }; - - [Theory] - [MemberData(nameof(NullableSum))] - public void Sum_With_Nullable_ValidData_Must_Succeed(int?[] source) - { - // Arrange - var wrapped = Wrap.AsList(source); - var expected = Enumerable - .Sum(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Sum(); - - // Assert - _ = result.Must() - .BeEqualTo(expected.Value); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncEnumerable.Tests.cs deleted file mode 100644 index 355ac9a4d..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncEnumerable.Tests.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsAsyncValueEnumerable -{ - public class AsyncEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsAsyncValueEnumerable_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsAsyncEnumerable(source); - - // Act - var result = AsyncEnumerableExtensions - .AsAsyncValueEnumerable(wrapped); - - // Assert - _ = result.Must() - .BeAsyncEnumerableOf() - .BeEqualTo(source); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask AsAsyncValueEnumerable_With_ToArrayAsync_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsAsyncEnumerable(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = await AsyncEnumerableExtensions - .AsAsyncValueEnumerable(wrapped) - .ToArrayAsync(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask AsAsyncValueEnumerable_With_ToListAsync_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsAsyncEnumerable(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = await AsyncEnumerableExtensions - .AsAsyncValueEnumerable(wrapped) - .ToListAsync(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsAsyncValueEnumerable_GetEnumerator_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsAsyncEnumerable(source); - - // Act - var result = AsyncEnumerableExtensions - .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, int>(wrapped, (enumerable, _) => enumerable.GetAsyncEnumerator()); - - // Assert - _ = result.Must() - .BeAsyncEnumerableOf() - .BeEqualTo(source); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask AsAsyncValueEnumerable_GetEnumerator_ToListAsync_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsAsyncEnumerable(source); - - // Act - var result = await AsyncEnumerableExtensions - .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, int>(wrapped, (enumerable, _) => enumerable.GetAsyncEnumerator()) - .ToListAsync(); - - // Assert - _ = result.Must() - .BeAsyncEnumerableOf() - .BeEqualTo(source); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask AsAsyncValueEnumerable_GetEnumerator_ToArrayAsync_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsAsyncEnumerable(source); - - // Act - var result = await AsyncEnumerableExtensions - .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, int>(wrapped, (enumerable, _) => enumerable.GetAsyncEnumerator()) - .ToArrayAsync(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(source); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncValueEnumerable.Tests.cs deleted file mode 100644 index 4ff502669..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncValueEnumerable.Tests.cs +++ /dev/null @@ -1,41 +0,0 @@ -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsAsyncValueEnumerable -{ - public class AsyncValueEnumerableTests - { - [Fact] - public void AsAsyncValueEnumerable_With_ValueType_Must_ReturnCopy() - { - // Arrange - var source = new int[0]; - var wrapped = Wrap.AsAsyncValueEnumerable(source); - - // Act - var result = AsyncValueEnumerableExtensions - .AsAsyncValueEnumerable, Wrap.AsyncEnumerator, int>(wrapped); - - // Assert - _ = result.Must() - .BeEqualTo(wrapped); - } - - [Fact] - public void AsAsyncValueEnumerable_With_ReferenceType_Must_ReturnSame() - { - // Arrange - var source = new int[0]; - var wrapped = Wrap - .AsAsyncValueEnumerable(source) as IAsyncValueEnumerable>; - - // Act - var result = AsyncValueEnumerableExtensions - .AsAsyncValueEnumerable>, Wrap.AsyncEnumerator, int>(wrapped); - - // Assert - _ = result.Must() - .BeSameAs(wrapped); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.ValueEnumerable.Tests.cs deleted file mode 100644 index 8a94affd6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.ValueEnumerable.Tests.cs +++ /dev/null @@ -1,104 +0,0 @@ -using NetFabric.Assertive; -using Xunit; -using System.Collections.Generic; -using System.Threading.Tasks; -using System; -using System.Linq; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsAsyncValueEnumerable -{ - public class ValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask AsAsyncValueEnumerable_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsValueEnumerable(source); - - // Act - var result = ValueEnumerableExtensions - .AsAsyncValueEnumerable, Wrap.Enumerator, int>(wrapped); - - // Assert - var enumerator = result.GetAsyncEnumerator(); - await using (enumerator.ConfigureAwait(false)) - { - var index = 0; - while (true) - { - var isResultCompleted = !await enumerator.MoveNextAsync(); - var isSourceCompleted = index == source.Length; - - if (isResultCompleted && isSourceCompleted) - return; - - if (isResultCompleted) - throw new Exception("'result' is shorter."); - - if (isSourceCompleted) - throw new Exception("'result' is longer."); - - if (!EqualityComparer.Default.Equals(enumerator.Current, source[index])) - throw new Exception($"Items are not equal at index '{index}'."); - - index++; - } - } - // TODO: figure out why this doesn't work... - //_ = result.Must() - // .BeAsyncEnumerableOf() - // .BeEqualTo(source); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask AsAsyncValueEnumerable_With_ToArrayAsync_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsValueEnumerable(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = await ValueEnumerableExtensions - .AsAsyncValueEnumerable, Wrap.Enumerator, int>(wrapped) - .ToArrayAsync(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask AsAsyncValueEnumerable_With_ToListAsync_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsValueEnumerable(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = await ValueEnumerableExtensions - .AsAsyncValueEnumerable, Wrap.Enumerator, int>(wrapped) - .ToListAsync(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.Enumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.Enumerable.Tests.cs deleted file mode 100644 index 61c366113..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.Enumerable.Tests.cs +++ /dev/null @@ -1,144 +0,0 @@ -using NetFabric.Assertive; -using Xunit; -using System.Collections.Generic; -using System.Linq; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable -{ - public class EnumerableTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsEnumerable(source); - - // Act - var result = EnumerableExtensions - .AsValueEnumerable(wrapped); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(wrapped); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ToArray_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsEnumerable(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = EnumerableExtensions - .AsValueEnumerable(wrapped) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ToList_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsEnumerable(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = EnumerableExtensions - .AsValueEnumerable(wrapped) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_GetEnumerator_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsEnumerable(source); - - // Act - var result = EnumerableExtensions - .AsValueEnumerable, Wrap.Enumerator, int>(wrapped, enumerable => enumerable.GetEnumerator()); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(wrapped); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_GetEnumerator_With_ToArray_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsEnumerable(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = EnumerableExtensions - .AsValueEnumerable, Wrap.Enumerator, int>(wrapped, enumerable => enumerable.GetEnumerator()) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_GetEnumerator_With_ToList_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsEnumerable(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = EnumerableExtensions - .AsValueEnumerable, Wrap.Enumerator, int>(wrapped, enumerable => enumerable.GetEnumerator()) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyCollection.Tests.cs deleted file mode 100644 index df1bef375..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyCollection.Tests.cs +++ /dev/null @@ -1,242 +0,0 @@ -using NetFabric.Assertive; -using Xunit; -using System.Collections.Generic; -using System.Linq; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable -{ - public class ReadOnlyCollectionTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable(wrapped); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(wrapped); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ToArray_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable(wrapped) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_Collection_With_ToArray_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsCollection(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable(wrapped) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ToList_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable(wrapped) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_Collection_With_ToList_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsCollection(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable(wrapped) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - ////////// - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_GetEnumerator_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable, Wrap.Enumerator, int>(wrapped, enumerable => enumerable.GetEnumerator()); - - // Assert - _ = result.Must() - .BeOfType, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>>() - .BeEnumerableOf() - .BeEqualTo(wrapped); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_GetEnumerator_With_ToArray_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable, Wrap.Enumerator, int>(wrapped, enumerable => enumerable.GetEnumerator()) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_GetEnumerator_Collection_With_ToArray_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsCollection(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable, Wrap.Enumerator, int>(wrapped, enumerable => enumerable.GetEnumerator()) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_GetEnumerator_With_ToList_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable, Wrap.Enumerator, int>(wrapped, enumerable => enumerable.GetEnumerator()) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_GetEnumerator_Collection_With_ToList_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsCollection(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable, Wrap.Enumerator, int>(wrapped, enumerable => enumerable.GetEnumerator()) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs deleted file mode 100644 index 5c4ab230a..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,125 +0,0 @@ -using NetFabric.Assertive; -using Xunit; -using System.Collections.Generic; -using System.Linq; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped - .AsValueEnumerable(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(wrapped); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ToArray_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = wrapped - .AsValueEnumerable() - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_Collection_With_ToArray_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsList(source); - var expected = Enumerable - .ToArray(source); - - // Act - var result = wrapped - .AsValueEnumerable() - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ToList_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = wrapped - .AsValueEnumerable() - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_Collection_With_ToList_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsList(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = wrapped - .AsValueEnumerable() - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ValueEnumerable.Tests.cs deleted file mode 100644 index 4fae4e922..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ValueEnumerable.Tests.cs +++ /dev/null @@ -1,41 +0,0 @@ -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable -{ - public class ValueEnumerableTests - { - [Fact] - public void AsValueEnumerable_With_ValueType_Must_ReturnCopy() - { - // Arrange - var source = new int[0]; - var wrapped = Wrap.AsValueEnumerable(source); - - // Act - var result = ValueEnumerableExtensions - .AsValueEnumerable, Wrap.Enumerator, int>(wrapped); - - // Assert - _ = result.Must() - .BeEqualTo(wrapped); - } - - [Fact] - public void AsValueEnumerable_With_ReferenceType_Must_ReturnSame() - { - // Arrange - var source = new int[0]; - var wrapped = Wrap - .AsValueEnumerable(source) as IValueEnumerable>; - - // Act - var result = ValueEnumerableExtensions - .AsValueEnumerable>, Wrap.Enumerator, int>(wrapped); - - // Assert - _ = result.Must() - .BeSameAs(wrapped); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ArraySegment.Tests.cs deleted file mode 100644 index cc1be5719..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ArraySegment.Tests.cs +++ /dev/null @@ -1,331 +0,0 @@ -using System; -using System.Buffers; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToArray -{ - public class ArraySegmentTests - { - [Fact] - public void ToArray_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - - // Act - var result = source.AsValueEnumerable() - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(Array.Empty()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void ToArray_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .ToArray(wrapped); - - // Act - var result = wrapped.AsValueEnumerable() - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void ToArray_MemoryPool_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var pool = MemoryPool.Shared; - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .ToArray(wrapped); - - // Act - var result = wrapped.AsValueEnumerable() - .ToArray(pool); - - // Assert - _ = result.Memory - .SequenceEqual(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Where(predicate) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var pool = MemoryPool.Shared; - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Where(predicate) - .ToArray(pool); - - // Assert - _ = result.Memory - .SequenceEqual(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void ToArray_PredicateAt_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Where(predicate) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void ToArray_PredicateAt_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var pool = MemoryPool.Shared; - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Where(predicate) - .ToArray(pool); - - // Assert - _ = result.Memory - .SequenceEqual(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Selector_Must_Succeed(int[] source, int skip, int take, Func selector) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Select(wrapped, selector) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Select(selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Selector_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Select(wrapped, selector) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Select(selector) - .ToArray(pool); - - // Assert - _ = result.Memory - .SequenceEqual(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void ToArray_SelectorAt_Must_Succeed(int[] source, int skip, int take, Func selector) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Select(wrapped, selector) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Select(selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void ToArray_SelectorAt_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Select(wrapped, selector) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Select(selector) - .ToArray(pool); - - // Assert - _ = result.Memory - .SequenceEqual(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Selector_Must_Succeed(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate) - .Select(selector) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Where(predicate) - .Select(selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Selector_MemoryPool_Must_Succeed(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate) - .Select(selector) - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Where(predicate) - .Select(selector) - .ToArray(pool); - - // Assert - _ = result.Memory - .SequenceEqual(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 5dde4d3d0..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,276 +0,0 @@ -using System; -using System.Buffers; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToArray -{ - public class ReadOnlyMemoryTests - { - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToArray_MemoryPool_Must_Succeed(int[] source) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .ToArray(source); - - // Act - using var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ToArray_PredicateAt_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ToArray_PredicateAt_MemoryPool_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Selector_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Selector_MemoryPool_Must_Succeed(int[] source, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ToArray_SelectorAt_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ToArray_SelectorAt_MemoryPool_Must_Succeed(int[] source, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Selector_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToArray(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .Select(selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Selector_MemoryPool_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .Select(selector) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlySpan.Tests.cs deleted file mode 100644 index 62ae28d52..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,276 +0,0 @@ -using System; -using System.Buffers; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToArray -{ - public class ReadOnlySpanTests - { - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToArray_MemoryPool_Must_Succeed(int[] source) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .ToArray(source); - - // Act - using var result = ArrayExtensions - .ToArray((ReadOnlySpan)source.AsSpan(), pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ToArray_PredicateAt_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ToArray_PredicateAt_MemoryPool_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Selector_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Selector_MemoryPool_Must_Succeed(int[] source, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ToArray_SelectorAt_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ToArray_SelectorAt_MemoryPool_Must_Succeed(int[] source, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Selector_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToArray(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Select(selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Selector_MemoryPool_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Select(selector) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.Span.Tests.cs deleted file mode 100644 index ad24e3324..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.Span.Tests.cs +++ /dev/null @@ -1,276 +0,0 @@ -using System; -using System.Buffers; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToArray -{ - public class SpanTests - { - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToArray_MemoryPool_Must_Succeed(int[] source) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .ToArray(source); - - // Act - using var result = ArrayExtensions - .ToArray(source.AsSpan(), pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ToArray_PredicateAt_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ToArray_PredicateAt_MemoryPool_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Selector_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Selector_MemoryPool_Must_Succeed(int[] source, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ToArray_SelectorAt_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ToArray_SelectorAt_MemoryPool_Must_Succeed(int[] source, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Selector_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToArray(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeNotSameAs(source) - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToArray_Predicate_Selector_MemoryPool_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToArray(); - - // Act - using var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .ToArray(pool); - - // Assert - _ = result.Memory.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Array.Tests.cs deleted file mode 100644 index 5126f6d87..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Array.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToList_With_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .ToList(source); - - // Act - var result = source.AsValueEnumerable() - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ArraySegment.Tests.cs deleted file mode 100644 index f4957b024..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ArraySegment.Tests.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList -{ - public class ArraySegmentTests - { - [Fact] - public void ToList_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - - // Act - var result = source.AsValueEnumerable() - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(new List()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void ToList_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .ToList(wrapped); - - // Act - var result = wrapped.AsValueEnumerable() - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void ToList_Predicate_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(wrapped, skip) - .Take(take) - .Where(predicate) - .ToList(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void ToList_PredicateAt_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(wrapped, skip) - .Take(take) - .Where(predicate) - .ToList(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void ToList_Selector_Must_Succeed(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(wrapped, skip) - .Take(take) - .Select(selector) - .ToList(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void ToList_SelectorAt_Must_Succeed(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(wrapped, skip) - .Take(take) - .Select(selector) - .ToList(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToList_Predicate_Selector_Must_Succeed(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(wrapped, skip) - .Take(take) - .Where(predicate) - .Select(selector) - .ToList(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Memory.Tests.cs deleted file mode 100644 index 1e126ba7c..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Memory.Tests.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToList_With_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .ToList(source); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ToList_With_Predicate_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Where(predicate) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ToList_With_PredicateAt_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Where(predicate) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ToList_With_Selector_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToList(); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Select(selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ToList_With_SelectorAt_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToList(); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Select(selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToList_With_Predicate_Selector_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToList(); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Where(predicate) - .Select(selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlyCollection.Tests.cs deleted file mode 100644 index 9c3dddf18..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlyCollection.Tests.cs +++ /dev/null @@ -1,59 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Collections.Generic; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList -{ - public class ReadOnlyCollectionTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToList_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable(wrapped) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToList_With_ValidData_Collections_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsCollection(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable(wrapped) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 783ba325e..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToList_With_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .ToList(source); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ToList_With_Predicate_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ToList_With_PredicateAt_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ToList_With_Selector_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToList(); - - // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ToList_With_SelectorAt_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToList(); - - // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToList_With_Predicate_Selector_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToList(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .Select(selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Span.Tests.cs deleted file mode 100644 index 1b94793c4..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToList.Span.Tests.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ToList_With_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .ToList(source); - - // Act - var result = ArrayExtensions - .ToList(source.AsSpan()); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ToList_With_Predicate_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ToList_With_PredicateAt_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ToList_With_Selector_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToList(); - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ToList_With_SelectorAt_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToList(); - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ToList_With_Predicate_Selector_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToList(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .ToList(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToListAsync.AsyncEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToListAsync.AsyncEnumerable.Tests.cs deleted file mode 100644 index 35756d627..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToList/ToListAsync.AsyncEnumerable.Tests.cs +++ /dev/null @@ -1,36 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Conversion.ToList -{ - public class AsyncEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public async ValueTask ToListAsync_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsAsyncEnumerable(source); - var expected = Enumerable - .ToList(source); - - // Act - var result = await AsyncEnumerableExtensions - .AsAsyncValueEnumerable(wrapped) - .ToListAsync(); - - // Assert - _ = result.Must() - .BeOfType>() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt.TestData.cs b/NetFabric.Hyperlinq.UnitTests/Element/ElementAt.TestData.cs deleted file mode 100644 index ba7230b05..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt.TestData.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using Xunit; - -namespace NetFabric.Hyperlinq -{ - public static partial class TestData - { - public static TheoryData ElementAtOutOfRange => - new TheoryData - { - { new int[] { }, -1 }, - { new int[] { }, 0 }, - { new int[] { }, 1 }, - { new int[] { 1 }, -1 }, - { new int[] { 1 }, 1 }, - { new int[] { 1, 2, 3, 4, 5 }, -1 }, - { new int[] { 1, 2, 3, 4, 5 }, 5 }, - }; - - public static TheoryData ElementAt => - new TheoryData - { - { new int[] { 1 }, 0}, - { new int[] { 1, 2, 3, 4, 5 }, 0 }, - { new int[] { 1, 2, 3, 4, 5 }, 2 }, - { new int[] { 1, 2, 3, 4, 5 }, 4 }, - }; - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.Array.Tests.cs deleted file mode 100644 index 179e89d4d..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.Array.Tests.cs +++ /dev/null @@ -1,52 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.ElementAt -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ElementAt_With_OutOfRange_Must_Return_None(int[] source) - { - // Arrange - - // Act - var optionTooSmall = source.AsValueEnumerable() - .ElementAt(-1); - var optionTooLarge = source.AsValueEnumerable() - .ElementAt(source.Length); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ElementAt_With_ValidData_Must_Return_Some(int[] source) - { - // Arrange - for (var index = 0; index < source.Length; index++) - { - // Act - var result = source.AsValueEnumerable() - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(source[index]), - () => throw new Exception()); - } - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ArraySegment.Tests.cs deleted file mode 100644 index 33155aba1..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ArraySegment.Tests.cs +++ /dev/null @@ -1,374 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.ElementAt -{ - public class ArraySegmentTests - { - [Fact] - public void ElementAt_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - - // Act - var result = source.AsValueEnumerable() - .ElementAt(0); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void ElementAt_With_OutOfRange_Must_Return_None(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .ElementAt(take); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void ElementAt_With_ValidData_Must_Return_Some(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .ToList(wrapped); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_With_OutOfRange_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .ElementAt(take); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_PredicateAt_With_OutOfRange_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .ElementAt(take); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_PredicateAt_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Selector_With_OutOfRange_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .ElementAt(take); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Selector_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .ElementAt(take); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_SelectorAt_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_Selector_With_OutOfRange_Must_Return_None(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .ElementAt(take); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Select(selector) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ReadOnlyList.Tests.cs deleted file mode 100644 index d30902644..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,409 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.ElementAt -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ElementAt_With_OutOfRange_Must_Return_None(int[] source) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .ElementAt(source.Length); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ElementAt_With_ValidData_Must_Return_Some(int[] source) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - - for (var index = 0; index < source.Length; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(source[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_With_OutOfRange_Must_Return_None(int[] source, int skipCount, int takeCount) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .ElementAt(takeCount); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_With_ValidData_Must_Return_Some(int[] source, int skipCount, int takeCount) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skipCount) - .Take(takeCount) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_Predicate_With_OutOfRange_Must_Return_None(int[] source, int skipCount, int takeCount, Func predicate) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Where(predicate) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Where(predicate) - .ElementAt(takeCount); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_Predicate_With_ValidData_Must_Return_Some(int[] source, int skipCount, int takeCount, Func predicate) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skipCount) - .Take(takeCount) - .Where(predicate) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Where(predicate) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_PredicateAt_With_OutOfRange_Must_Return_None(int[] source, int skipCount, int takeCount, Func predicate) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Where(predicate) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Where(predicate) - .ElementAt(takeCount); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_PredicateAt_With_ValidData_Must_Return_Some(int[] source, int skipCount, int takeCount, Func predicate) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skipCount) - .Take(takeCount) - .Where(predicate) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Where(predicate) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_Selector_With_OutOfRange_Must_Return_None(int[] source, int skipCount, int takeCount, Func selector) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Select(selector) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Select(selector) - .ElementAt(takeCount); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_Selector_With_ValidData_Must_Return_Some(int[] source, int skipCount, int takeCount, Func selector) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skipCount) - .Take(takeCount) - .Select(selector) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Select(selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, int skipCount, int takeCount, Func selector) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Select(selector) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Select(selector) - .ElementAt(takeCount); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_SelectorAt_With_ValidData_Must_Return_Some(int[] source, int skipCount, int takeCount, Func selector) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skipCount) - .Take(takeCount) - .Select(selector) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Select(selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_Predicate_Selector_With_OutOfRange_Must_Return_None(int[] source, int skipCount, int takeCount, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - - // Act - var optionTooSmall = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Where(predicate) - .Select(selector) - .ElementAt(-1); - var optionTooLarge = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Where(predicate) - .Select(selector) - .ElementAt(takeCount); - - // Assert - _ = optionTooSmall.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Skip_Take_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, int skipCount, int takeCount, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skipCount) - .Take(takeCount) - .Where(predicate) - .Select(selector) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Where(predicate) - .Select(selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 4cc19ab1b..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,304 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.ElementAt -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ElementAt_With_OutOfRange_Must_Return_None(int[] source) - { - // Arrange - - // Act - var optionNegative = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .ElementAt(-1); - var optionTooLarge = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ElementAt_With_ValidData_Must_Return_Some(int[] source) - { - for (var index = 0; index < source.Length; index++) - { - // Arrange - var expected = Enumerable - .ElementAt(source, index); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_With_OutOfRange_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_PredicateAt_With_OutOfRange_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Selector_With_OutOfRange_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) - { - for (var index = 0; index < source.Length; index++) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ElementAt(index); - - // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToList(); - - for (var index = 0; index < source.Length; index++) - { - // Act - var result = ArrayExtensions - .Select((ReadOnlyMemory)source.AsMemory(), selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_Selector_With_OutOfRange_Must_Return_None(int[] source, Func predicate, Func selector) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .Select(selector) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .Select(selector) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .Select(selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.Span.Tests.cs deleted file mode 100644 index d278ecd20..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/ElementAt/ElementAt.Span.Tests.cs +++ /dev/null @@ -1,304 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.ElementAt -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ElementAt_With_OutOfRange_Must_Return_None(int[] source) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .ElementAt(source.AsSpan(), -1); - var optionTooLarge = ArrayExtensions - .ElementAt(source.AsSpan(), source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void ElementAt_With_ValidData_Must_Return_Some(int[] source) - { - for (var index = 0; index < source.Length; index++) - { - // Arrange - var expected = Enumerable - .ElementAt(source, index); - - // Act - var result = ArrayExtensions - .ElementAt(source.AsSpan(), index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_With_OutOfRange_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_PredicateAt_With_OutOfRange_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Selector_With_OutOfRange_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Select(source.AsSpan(), selector) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Select(source.AsSpan(), selector) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToList(); - - for (var index = 0; index < source.Length; index++) - { - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_SelectorAt_With_OutOfRange_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Select(source.AsSpan(), selector) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Select(source.AsSpan(), selector) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void ElementAt_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToList(); - - for (var index = 0; index < source.Length; index++) - { - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_Selector_With_OutOfRange_Must_Return_None(int[] source, Func predicate, Func selector) - { - // Arrange - - // Act - var optionNegative = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .ElementAt(-1); - var optionTooLarge = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .ElementAt(source.Length); - - // Assert - _ = optionNegative.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - _ = optionTooLarge.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void ElementAt_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .ToList(); - - for (var index = 0; index < expected.Count; index++) - { - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .ElementAt(index); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected[index]), - () => throw new Exception()); - } - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/First.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/First/First.Array.Tests.cs deleted file mode 100644 index 3aa434eb9..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/First.Array.Tests.cs +++ /dev/null @@ -1,45 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.First -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - public void First_With_Empty_Must_Return_None(int[] source) - { - // Arrange - - // Act - var result = source.AsValueEnumerable() - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void First_With_ValidData_Must_Return_Some(int[] source) - { - // Arrange - var expected = Enumerable - .First(source); - - // Act - var result = source.AsValueEnumerable() - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/First/First.ArraySegment.Tests.cs deleted file mode 100644 index a6defd14a..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ArraySegment.Tests.cs +++ /dev/null @@ -1,297 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.First -{ - public class ArraySegmentTests - { - [Fact] - public void First_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - - // Act - var result = source.AsValueEnumerable() - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - public void First_With_Empty_Must_Return_None(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - - // Act - var result = wrapped.AsValueEnumerable() - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void First_With_ValidData_Must_Return_Some(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .First(wrapped); - - // Act - var result = wrapped.AsValueEnumerable() - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - public void First_Predicate_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void First_Predicate_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .First(predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - public void First_PredicateAt_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void First_PredicateAt_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(wrapped, skip) - .Take(take) - .Where(predicate) - .First(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - public void First_Selector_With_Empty_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void First_Selector_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .First(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtEmpty), MemberType = typeof(TestData))] - public void First_SelectorAt_With_Empty_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void First_SelectorAt_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .First(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - public void First_Predicate_Selector_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void First_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Select(selector) - .First(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/First/First.ReadOnlyList.Tests.cs deleted file mode 100644 index d238f8355..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,336 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.First -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - public void First_With_Empty_Must_Return_None(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void First_With_ValidData_Must_Return_Some(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .First(source); - - // Act - var result = wrapped.AsValueEnumerable() - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - public void First_SkipTake_With_Empty_Must_Return_None(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void First_SkipTake_With_ValidData_Must_Return_Some(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .First(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - public void First_Predicate_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void First_Predicate_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .First(predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - public void First_PredicateAt_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void First_PredicateAt_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(wrapped, skip) - .Take(take) - .Where(predicate) - .First(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - public void First_Selector_With_Empty_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void First_Selector_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .First(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtEmpty), MemberType = typeof(TestData))] - public void First_SelectorAt_With_Empty_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void First_SelectorAt_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .First(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - public void First_Predicate_Selector_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void First_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Select(selector) - .First(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/First/First.ReadOnlySpan.Tests.cs deleted file mode 100644 index 78502a04d..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/First.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,237 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.First -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - public void First_With_Empty_Must_Return_None(int[] source) - { - // Arrange - - // Act - var result = ArrayExtensions - .First((ReadOnlySpan)source.AsSpan()); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void First_With_ValidData_Must_Return_Some(int[] source) - { - // Arrange - var expected = Enumerable - .First(source); - - // Act - var result = ArrayExtensions - .First((ReadOnlySpan)source.AsSpan()); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - public void First_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void First_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .First(source, predicate); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - public void First_PredicateAt_With_Empty_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void First_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .First(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - public void First_Selector_With_Empty_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void First_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .First(); - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - public void First_SelectorAt_With_Empty_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void First_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .First(); - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - public void First_Predicate_Selector_With_Empty_Must_Return_None(int[] source, Func predicate, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Select(selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void First_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .First(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Select(selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/First/First.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/First/First.Span.Tests.cs deleted file mode 100644 index 7570b9b50..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/First/First.Span.Tests.cs +++ /dev/null @@ -1,237 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.First -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - public void First_With_Empty_Must_Return_None(int[] source) - { - // Arrange - - // Act - var result = ArrayExtensions - .First(source.AsSpan()); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void First_With_ValidData_Must_Return_Some(int[] source) - { - // Arrange - var expected = Enumerable - .First(source); - - // Act - var result = ArrayExtensions - .First(source.AsSpan()); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - public void First_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void First_Predicate_With_ValidData_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .First(source, predicate); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - public void First_PredicateAt_With_Empty_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void First_PredicateAt_With_ValidData_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .First(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - public void First_Selector_With_Empty_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void First_Selector_With_ValidData_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .First(); - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - public void First_SelectorAt_With_Empty_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void First_SelectorAt_With_ValidData_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .First(); - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - public void First_Predicate_Selector_With_Empty_Must_Return_None(int[] source, Func predicate, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .First(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void First_Predicate_Selector_With_ValidData_Must_Return_Some(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .First(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .First(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.Array.Tests.cs deleted file mode 100644 index 68c8e1114..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.Array.Tests.cs +++ /dev/null @@ -1,60 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.Single -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - public void Single_With_Empty_Must_Return_None(int[] source) - { - // Arrange - - // Act - var result = source.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - public void Single_With_Single_Must_Return_Some(int[] source) - { - // Arrange - var expected = Enumerable - .Single(source); - - // Act - var result = source.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Single_With_Multiple_Must_Return_None(int[] source) - { - // Arrange - - // Act - var result = source.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ArraySegment.Tests.cs deleted file mode 100644 index 3af0b7f13..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ArraySegment.Tests.cs +++ /dev/null @@ -1,471 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.Single -{ - public class ArraySegmentTests - { - [Fact] - public void Single_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - - // Act - var result = source.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - public void Single_With_Empty_Must_Return_None(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - - // Act - var result = wrapped.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - public void Single_With_Single_Must_Return_Some(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Single(wrapped); - - // Act - var result = wrapped.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Single_With_Multiple_Must_Return_None(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - - // Act - var result = wrapped.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - public void Single_SkipTake_With_Empty_Must_Return_None(int[] source, int skip, int take) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - public void Single_SkipTake_With_Single_Must_Return_Some(int[] source, int skip, int take) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Single_SkipTake_With_Multiple_Must_Return_None(int[] source, int skip, int take) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - public void Single_Predicate_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - public void Single_Predicate_With_Single_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Single(predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void Single_Predicate_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Single_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - public void Single_Selector_With_Empty_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - public void Single_Selector_With_Single_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void Single_Selector_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtEmpty), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Empty_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Single_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Single_Must_Return_Some(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Select(selector) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = new ArraySegment(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ReadOnlyList.Tests.cs deleted file mode 100644 index 5ee477522..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,473 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.Single -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - public void Single_With_Empty_Must_Return_None(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - public void Single_With_Single_Must_Return_Some(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Single(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Single_With_Multiple_Must_Return_None(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - public void Single_SkipTake_With_Empty_Must_Return_None(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - public void Single_SkipTake_With_Single_Must_Return_Some(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Single_SkipTake_With_Multiple_Must_Return_None(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - public void Single_Predicate_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - public void Single_Predicate_With_Single_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Single(predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void Single_Predicate_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Single_Must_Return_Some(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - public void Single_Selector_With_Empty_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - public void Single_Selector_With_Single_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void Single_Selector_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtEmpty), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Empty_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtSingle), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Single_Must_Return_Some(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorAtMultiple), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Empty_Must_Return_None(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Single_Must_Return_Some(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Select(selector) - .Single(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Multiple_Must_Return_None(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ReadOnlySpan.Tests.cs deleted file mode 100644 index e19ad21e1..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,333 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.Single -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - public void Single_With_Empty_Must_Return_None(int[] source) - { - // Arrange - - // Act - var result = ArrayExtensions - .Single((ReadOnlySpan)source.AsSpan()); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - public void Single_With_Single_Must_Return_Some(int[] source) - { - // Arrange - var expected = Enumerable - .Single(source); - - // Act - var result = ArrayExtensions - .Single((ReadOnlySpan)source.AsSpan()); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Single_With_Multiple_Must_Return_None(int[] source) - { - // Arrange - - // Act - var result = ArrayExtensions - .Single((ReadOnlySpan)source.AsSpan()); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - public void Single_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - public void Single_Predicate_With_Single_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = - Enumerable.Single(source, predicate); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Single_Predicate_With_Multiple_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Empty_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Single_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Single(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Multiple_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - public void Single_Selector_With_Empty_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - public void Single_Selector_With_Single_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = - Enumerable.Single( - Enumerable.Select(source, selector)); - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Single_Selector_With_Multiple_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Empty_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Single_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .Single(); - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Multiple_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select((ReadOnlySpan)source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Empty_Must_Return_None(int[] source, Func predicate, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Single_Must_Return_Some(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .Single(); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Multiple_Must_Return_None(int[] source, Func predicate, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.Span.Tests.cs deleted file mode 100644 index d4d009929..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Element/Single/Single.Span.Tests.cs +++ /dev/null @@ -1,333 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Element.Single -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - public void Single_With_Empty_Must_Return_None(int[] source) - { - // Arrange - - // Act - var result = ArrayExtensions - .Single(source.AsSpan()); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - public void Single_With_Single_Must_Return_Some(int[] source) - { - // Arrange - var expected = Enumerable - .Single(source); - - // Act - var result = ArrayExtensions - .Single(source.AsSpan()); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Single_With_Multiple_Must_Return_None(int[] source) - { - // Arrange - - // Act - var result = ArrayExtensions - .Single(source.AsSpan()); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - public void Single_Predicate_With_Empty_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - public void Single_Predicate_With_Single_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = - Enumerable.Single(source, predicate); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Single_Predicate_With_Multiple_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Empty_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Single_Must_Return_Some(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Single(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Single_PredicateAt_With_Multiple_Must_Return_None(int[] source, Func predicate) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - public void Single_Selector_With_Empty_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - public void Single_Selector_With_Single_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = - Enumerable.Single( - Enumerable.Select(source, selector)); - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Single_Selector_With_Multiple_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Empty_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Single_Must_Return_Some(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .Single(); - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Single_SelectorAt_With_Multiple_Must_Return_None(int[] source, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Select(source.AsSpan(), selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Empty_Must_Return_None(int[] source, Func predicate, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Single_Must_Return_Some(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector) - .Single(); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Match( - value => value.Must().BeEqualTo(expected), - () => throw new Exception()); - } - - [Theory] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void Single_Predicate_Selector_With_Multiple_Must_Return_None(int[] source, Func predicate, Func selector) - { - // Arrange - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector) - .Single(); - - // Assert - _ = result.Must() - .BeOfType>() - .EvaluateTrue(option => option.IsNone); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.Array.Tests.cs deleted file mode 100644 index cb90b84a9..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.Array.Tests.cs +++ /dev/null @@ -1,54 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = source.AsValueEnumerable() - .Where(predicate); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.PredicatePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicatePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicatePredicateMultiple), MemberType = typeof(TestData))] - public void Where_Where_With_ValidData_Must_Succeed(int[] source, Func predicate0, Func predicate1) - { - // Arrange - var expected = Enumerable - .Where(source, predicate0) - .Where(predicate1); - - // Act - var result = source.AsValueEnumerable() - .Where(predicate0) - .Where(predicate1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.AsyncValueEnumerable.Tests.cs deleted file mode 100644 index cf9890c54..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.AsyncValueEnumerable.Tests.cs +++ /dev/null @@ -1,34 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where -{ - public class AsyncValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()); - - // Assert - _ = result.Must() - .BeAsyncEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.Memory.Tests.cs deleted file mode 100644 index 1f3c862e2..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.Memory.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = System.Linq.Enumerable.Where(source, predicate); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Where(predicate); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyList.Tests.cs deleted file mode 100644 index 033f08ebb..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,37 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate); - - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 54c8796e2..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable.Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.Span.Tests.cs deleted file mode 100644 index d75a5014f..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.Span.Tests.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ValueEnumerable.Tests.cs deleted file mode 100644 index 99d324935..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ValueEnumerable.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.Where -{ - public class ValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.Array.Tests.cs deleted file mode 100644 index 13d36d94b..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.Array.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereAt -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = source.AsValueEnumerable() - .Where(predicate); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.AsyncValueEnumerable.Tests.cs deleted file mode 100644 index 67296c8a8..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.AsyncValueEnumerable.Tests.cs +++ /dev/null @@ -1,34 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereAt -{ - public class AsyncValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Where_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsAsyncValueEnumerable(source); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()); - - // Assert - _ = result.Must() - .BeAsyncEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.Memory.Tests.cs deleted file mode 100644 index c7a94e6cc..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.Memory.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereIndex -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Where(predicate); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyList.Tests.cs deleted file mode 100644 index e12d9ec96..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,36 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereAt -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 0d39eaa94..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereIndex -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.Span.Tests.cs deleted file mode 100644 index da5afab63..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.Span.Tests.cs +++ /dev/null @@ -1,28 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereIndex -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ValueEnumerable.Tests.cs deleted file mode 100644 index b399db06e..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ValueEnumerable.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereAt -{ - public class ValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Where_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap - .AsValueEnumerable(source); - var expected = Enumerable - .Where(wrapped, predicate); - - // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.Array.Tests.cs deleted file mode 100644 index 6588517ea..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.Array.Tests.cs +++ /dev/null @@ -1,34 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRef -{ - public class ArrayTests - { -/* - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void WhereRef_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = source.AsValueEnumerableRef() - .Where(function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefReturns: false, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } -*/ - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.ArraySegment.Tests.cs deleted file mode 100644 index 0f11e2fd3..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.ArraySegment.Tests.cs +++ /dev/null @@ -1,53 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRef -{ - public class ArraySegmentTests - { - [Fact] - public void WhereRef_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - var function = Wrap.AsFunctionIn(_ => true); - var expected = Enumerable.Empty(); - - // Act - var result = ArrayExtensions - .Where(source, function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefReturns: false, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void WhereRef_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(wrapped, predicate); - - // Act - var result = ArrayExtensions - .Where(wrapped, function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefReturns: false, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.Memory.Tests.cs deleted file mode 100644 index a0751afc8..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.Memory.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRef -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void WhereRef_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = source.AsMemory().AsValueEnumerableRef() - .Where(function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 840835c76..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRef -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void WhereRef_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.ReadOnlySpan.Tests.cs deleted file mode 100644 index dd16d2ff6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRef -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void WhereRef_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), function); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.Span.Tests.cs deleted file mode 100644 index 2afbd42a3..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRef/WhereRef.Span.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRef -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void WhereRef_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), function); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.Array.Tests.cs deleted file mode 100644 index 35b8331c4..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.Array.Tests.cs +++ /dev/null @@ -1,34 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereAtRef -{ - public class ArrayTests - { -/* - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void WhereAtRef_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = source.AsValueEnumerableRef() - .Where(function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } -*/ - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.ArraySegment.Tests.cs deleted file mode 100644 index 2ada0b4e6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.ArraySegment.Tests.cs +++ /dev/null @@ -1,53 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereAtRef -{ - public class ArraySegmentTests - { - [Fact] - public void WhereAtRef_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - var function = Wrap.AsFunctionIn((_, __) => true); - var expected = Enumerable.Empty(); - - // Act - var result = ArrayExtensions - .Where(source, function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void WhereAtRef_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(wrapped, predicate); - - // Act - var result = ArrayExtensions - .Where(wrapped, function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.Memory.Tests.cs deleted file mode 100644 index 70438089d..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.Memory.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRefIndex -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void WhereAtRef_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = source.AsMemory().AsValueEnumerableRef() - .Where(function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 27cda9295..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRefIndex -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void WhereAtRef_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), function); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.ReadOnlySpan.Tests.cs deleted file mode 100644 index 97143bedf..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRefIndex -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void WhereAtRef_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), function); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.Span.Tests.cs deleted file mode 100644 index 5175bebed..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereRefAt/WhereRefAt.Span.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereRefIndex -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void WhereAtRef_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var function = Wrap.AsFunctionIn(predicate); - var expected = Enumerable - .Where(source, predicate); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), function); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.Array.Tests.cs deleted file mode 100644 index dac06a3b9..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.Array.Tests.cs +++ /dev/null @@ -1,33 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = Enumerable - .Where(source, predicate) - .Select(selector); - - // Act - var result = source.AsValueEnumerable() - .Where(predicate) - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.AsyncValueEnumerable.Tests.cs deleted file mode 100644 index 74a45afc2..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.AsyncValueEnumerable.Tests.cs +++ /dev/null @@ -1,34 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect -{ - public class AsyncValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void WhereSelect_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(source, predicate), selector); - - // Act - var result = AsyncValueEnumerableExtensions - .Where, Wrap.AsyncEnumerator, int>(wrapped, predicate.AsAsync()) - .Select(selector.AsAsync()); - - // Assert - _ = result.Must() - .BeAsyncEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.Memory.Tests.cs deleted file mode 100644 index 0d2571f6e..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.Memory.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(source, predicate), selector); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Where(predicate) - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyList.Tests.cs deleted file mode 100644 index 0553fc018..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,37 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSelectorMultiple), MemberType = typeof(TestData))] - public void WhereSelect_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Where(predicate) - .Select(selector); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Where(predicate) - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 83f8cc644..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(source, predicate), selector); - - // Act - var result = ArrayExtensions - .Where((ReadOnlyMemory)source.AsMemory(), predicate) - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlySpan.Tests.cs deleted file mode 100644 index 5b61db349..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(source, predicate), selector); - - // Act - var result = ArrayExtensions - .Where((ReadOnlySpan)source.AsSpan(), predicate) - .Select(selector); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.Span.Tests.cs deleted file mode 100644 index cd389352b..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.Span.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(source, predicate), selector); - - // Act - var result = ArrayExtensions - .Where(source.AsSpan(), predicate) - .Select(selector); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ValueEnumerable.Tests.cs deleted file mode 100644 index fa504c24a..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ValueEnumerable.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Filtering.WhereSelect -{ - public class ValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.PredicateSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSelectorMultiple), MemberType = typeof(TestData))] - public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func predicate, Func selector) - { - // Arrange - var wrapped = Wrap.AsValueEnumerable(source); - var expected = - System.Linq.Enumerable.Select( - System.Linq.Enumerable.Where(wrapped, predicate), selector); - - // Act - var result = ValueEnumerableExtensions - .Where, Wrap.Enumerator, int>(wrapped, predicate) - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/GenerateSourceTests.cs b/NetFabric.Hyperlinq.UnitTests/GenerateSourceTests.cs new file mode 100644 index 000000000..5d0ee0543 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/GenerateSourceTests.cs @@ -0,0 +1,148 @@ +using Microsoft.CodeAnalysis.CSharp.Syntax; +using NetFabric.Assertive; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace NetFabric.Hyperlinq.SourceGenerator.UnitTests +{ + public class GenerateSourceTests + { + public static TheoryData GeneratorSources + => new() + { + { + new[] { "TestData/Source/AsValueEnumerable.Empty.cs" }, + "TestData/Results/Empty.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.Empty2.cs" }, + "TestData/Results/Empty.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.Empty3.cs" }, + "TestData/Results/Empty.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.Repeat.cs" }, + "TestData/Results/AsValueEnumerable.Repeat.cs" + }, + + { + new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs" }, + "TestData/Results/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs" }, + "TestData/Results/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs" }, + "TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs" }, + "TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs" }, + "TestData/Results/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestCollection.cs" }, + "TestData/Results/AsValueEnumerable.TestCollection.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestReadOnlyCollection.cs" }, + "TestData/Results/AsValueEnumerable.TestReadOnlyCollection.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestList.cs" }, + "TestData/Results/AsValueEnumerable.TestList.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.IReadOnlyList.cs" }, + "TestData/Results/AsValueEnumerable.IReadOnlyList.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestListWithExplicitInterfaces.cs" }, + "TestData/Results/AsValueEnumerable.TestListWithExplicitInterfaces.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestReadOnlyList.cs" }, + "TestData/Results/AsValueEnumerable.TestReadOnlyList.cs" + }, + { + new[] { "TestData/Source/AsValueEnumerable.TestValueEnumerable.cs" }, + "TestData/Results/AsValueEnumerable.TestValueEnumerable.cs" + }, + { + new[] { "TestData/Source/Count.Array.cs" }, + "TestData/Results/Count.Array.cs" + }, + { + new[] { "TestData/Source/Select.Array.cs" }, + "TestData/Results/Select.Array.cs" + }, + { + new[] { "TestData/Source/Where.Array.cs" }, + "TestData/Results/Where.Array.cs" + }, + { + new[] { "TestData/Source/Skip.Take.Array.cs" }, + "TestData/Results/Skip.Take.Array.cs" + }, + //{ + // new[] { "TestData/Source/Count.Span.cs" }, + // "TestData/Results/Count.Span.cs" + //}, + { + new[] { "TestData/Source/AsEnumerable.TestEnumerableWithValueTypeEnumerator.cs" }, + "TestData/Results/AsEnumerable.TestEnumerableWithValueTypeEnumerator.cs" + }, + { + new[] { "TestData/Source/Select.TestEnumerableWithValueTypeEnumerator.cs" }, + "TestData/Results/Select.TestEnumerableWithValueTypeEnumerator.cs" + }, + }; + + [Theory] + [MemberData(nameof(GeneratorSources))] + public async Task GenerateSourceShouldGenerate(string[] paths, string expected) + { + // Arrange + var sources = paths + .Concat(Directory.EnumerateFiles("TestData/Source/Common", "*.cs", SearchOption.AllDirectories)) + .Select(path => File.ReadAllText(path)); + var project = Verifier.CreateProject(sources); + var compilation = await project.GetCompilationAsync().ConfigureAwait(false) + ?? throw new System.Exception("Error getting compilation!"); + //var errors = compilation + // .GetDiagnostics() + // .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error) + // .ToArray(); + //_ = errors.Must().BeEqualTo(Array.Empty()); + var typeSymbolsCache = new TypeSymbolsCache(compilation); + var memberAccessExpressions = compilation.SyntaxTrees + .SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()) + .Where(memberAccess => Generator.methods.Contains(memberAccess.Name.Identifier.ValueText)) + .ToList(); + + // Act + var builder = new CodeBuilder { IsUnitTest = true }; + Generator.GenerateSource(compilation, typeSymbolsCache, memberAccessExpressions, builder, CancellationToken.None); + var result = builder.ToString(); + + // Assert +#if NET5_0_OR_GREATER + _ = result.Must() + .BeEqualTo(await File.ReadAllTextAsync(expected)); +#else + _ = result.Must() + .BeEqualTo(File.ReadAllText(expected)); +#endif + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj b/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj index b23123814..39ba44d1e 100644 --- a/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj +++ b/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj @@ -1,43 +1,42 @@  - net461;netcoreapp2.1;netcoreapp3.1;net5.0 + net6.0 + false + true + + + + NOT_TESTING - - - - - - all + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - runtime; build; native; contentfiles; analyzers - - - - - + + Always + diff --git a/NetFabric.Hyperlinq.UnitTests/Option/TestData.Option.cs b/NetFabric.Hyperlinq.UnitTests/Option/TestData.Option.cs deleted file mode 100644 index 6a70cef3e..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Option/TestData.Option.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using Xunit; - -namespace NetFabric.Hyperlinq -{ - public static partial class TestData - { - public static TheoryData OptionSome => - new TheoryData - { - { (string)null }, - { string.Empty }, - { "string" }, - }; - - public static TheoryData OptionNoneSelectMany => - new TheoryData - { - { new int[] { } }, - { new int[] { 1 } }, - { new int[] { 1, 2, 3, 4, 5 } }, - }; - - public static TheoryData OptionSomeSelectMany => - new TheoryData - { - { (string)null, new int[] { } }, - { (string)null, new int[] { 1 } }, - { (string)null, new int[] { 1, 2, 3, 4, 5 } }, - { string.Empty, new int[] { } }, - { string.Empty, new int[] { 1 } }, - { string.Empty, new int[] { 1, 2, 3, 4, 5 } }, - { "string", new int[] { } }, - { "string", new int[] { 1 } }, - { "string", new int[] { 1, 2, 3, 4, 5 } }, - }; - - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip.TestData.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip.TestData.cs deleted file mode 100644 index a0359620f..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip.TestData.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; -using Xunit; - -namespace NetFabric.Hyperlinq -{ - public static partial class TestData - { - public static TheoryData Skip_Skip => - new TheoryData - { - { new int[] { }, -1, -1 }, - { new int[] { }, 0, -1 }, - { new int[] { }, 1, -1 }, - - { new int[] { }, -1, 0 }, - { new int[] { }, 0, 0 }, - { new int[] { }, 1, 0 }, - - { new int[] { 1 }, -1, -1 }, - { new int[] { 1 }, 0, 0 }, - { new int[] { 1 }, 1, 1 }, - { new int[] { 1 }, 5, 5 }, - - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, -1 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 0 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 2 }, - }; - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.Array.Tests.cs deleted file mode 100644 index 4eb816ac4..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.Array.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] - public void Skip_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Skip(source, count); - - // Act - var result = source.AsValueEnumerable() - .Skip(count); - - // Assert - _ = result - .SequenceEqual(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ArraySegment.Tests.cs deleted file mode 100644 index 4bce8af2b..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ArraySegment.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip -{ - public class ArraySegmentTests - { - [Theory] - [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] - public void Skip_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Skip(source, count); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.Memory.Tests.cs deleted file mode 100644 index a4224d574..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.Memory.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] - public void Skip_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Skip(source, count); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Skip(count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ReadOnlyList.Tests.cs deleted file mode 100644 index 9d62edb75..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] - public void Skip_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyList(source); - var expected = Enumerable - .Skip(source, count); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 74082c480..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] - public void Skip_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Skip(source, count); - - // Act - var result = ArrayExtensions - .Skip((ReadOnlyMemory)source.AsMemory(), count); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ReadOnlySpan.Tests.cs deleted file mode 100644 index 0483482b1..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] - public void Skip_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Skip(source, count); - - // Act - var result = ArrayExtensions - .Skip((ReadOnlySpan)source.AsSpan(), count); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.Span.Tests.cs deleted file mode 100644 index 6240795d6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.Span.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] - public void Skip_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Skip(source, count); - - // Act - var result = ArrayExtensions - .Skip(source.AsSpan(), count); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueReadOnlyCollection.Tests.cs deleted file mode 100644 index fcaeb6cbb..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueReadOnlyCollection.Tests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using NetFabric.Assertive; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip -{ - public class ValueReadOnlyCollectionTests - { - [Theory] - [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] - public void Skip_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyCollection(source); - var expected = Enumerable - .Skip(wrapped, count); - - // Act - var result = ValueReadOnlyCollectionExtensions.Skip, Wrap.Enumerator, int>(wrapped, count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/SkipTake.TestData.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/SkipTake.TestData.cs deleted file mode 100644 index 125ce3184..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/SkipTake.TestData.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using Xunit; - -namespace NetFabric.Hyperlinq -{ - public static partial class TestData - { - public static TheoryData SkipTake_Take => - new TheoryData - { - { new int[] { }, 0, 0, -1 }, - { new int[] { }, 0, 0, 0 }, - { new int[] { }, 0, 0, 1 }, - - { new int[] { 1 }, 0, 1, -1 }, - { new int[] { 1 }, 0, 1, 0 }, - { new int[] { 1 }, 0, 1, 1 }, - { new int[] { 1 }, 0, 1, 5 }, - - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 2, -1 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 2, 0 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 2, 5 }, - }; - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take.TestData.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Take.TestData.cs deleted file mode 100644 index 47afbaedc..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take.TestData.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using Xunit; - -namespace NetFabric.Hyperlinq -{ - public static partial class TestData - { - public static TheoryData Take_Take => - new TheoryData - { - { new int[] { }, -1, -1 }, - { new int[] { }, 0, -1 }, - { new int[] { }, 1, -1 }, - - { new int[] { }, -1, 0 }, - { new int[] { }, 0, 0 }, - { new int[] { }, 1, 0 }, - - { new int[] { 1 }, -1, -1 }, - { new int[] { 1 }, 0, 0 }, - { new int[] { 1 }, 0, 1 }, - { new int[] { 1 }, 1, 1 }, - { new int[] { 1 }, 5, 2 }, - { new int[] { 1 }, 5, 5 }, - - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, -1 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 2 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 0 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 1 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4 }, - }; - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.Array.Tests.cs deleted file mode 100644 index ae3ea43a5..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.Array.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] - public void Take_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Take(source, count); - - // Act - var result = source.AsValueEnumerable() - .Take(count); - - // Assert - _ = result - .SequenceEqual(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ArraySegment.Tests.cs deleted file mode 100644 index 5389c5d69..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ArraySegment.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take -{ - public class ArraySegmentTests - { - [Theory] - [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] - public void Take_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = Enumerable - .Take(source, count); - - // Act - var result = wrapped.AsValueEnumerable() - .Take(count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.Memory.Tests.cs deleted file mode 100644 index ac2ea89bc..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.Memory.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] - public void Take_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Take(source, count); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Take(count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ReadOnlyList.Tests.cs deleted file mode 100644 index 22d468008..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] - public void Take_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyList(source); - var expected = Enumerable - .Take(source, count); - - // Act - var result = wrapped.AsValueEnumerable() - .Take(count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ReadOnlyMemory.Tests.cs deleted file mode 100644 index ec8c4a20d..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] - public void Take_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Take(source, count); - - // Act - var result = ArrayExtensions - .Take((ReadOnlyMemory)source.AsMemory(), count); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ReadOnlySpan.Tests.cs deleted file mode 100644 index f42e9530e..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] - public void Take_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Take(source, count); - - // Act - var result = ArrayExtensions - .Take((ReadOnlySpan)source.AsSpan(), count); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.Span.Tests.cs deleted file mode 100644 index 54167aa9c..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.Span.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] - public void Take_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var expected = Enumerable - .Take(source, count); - - // Act - var result = ArrayExtensions - .Take(source.AsSpan(), count); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ValueReadOnlyCollection.Tests.cs deleted file mode 100644 index 8a71e4553..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Take/Take.ValueReadOnlyCollection.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Take -{ - public class ValueReadOnlyCollectionTests - { - [Theory] - [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] - public void Take_With_ValidData_Must_Succeed(int[] source, int count) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyCollection(source); - var expected = Enumerable - .Take(wrapped, count); - - // Act - var result = ValueReadOnlyCollectionExtensions - .Take, Wrap.Enumerator, int>(wrapped, count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.Array.Tests.cs deleted file mode 100644 index 354d87a18..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.Array.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.Select -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector); - - // Act - var result = source.AsValueEnumerable() - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.AsyncValueEnumerable.Tests.cs deleted file mode 100644 index a8fe74aef..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.AsyncValueEnumerable.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.Select -{ - public class AsyncValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Select_Selector_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = System.Linq.Enumerable - .Select(source, selector); - - // Act - var result = AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()); - - // Assert - _ = result.Must() - .BeAsyncEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.Memory.Tests.cs deleted file mode 100644 index 408522984..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.Memory.Tests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.Select -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select(source, selector); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyList.Tests.cs deleted file mode 100644 index 89416a7ad..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.Select -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.SkipTakeSelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSelectorMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func selector) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Select(selector); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 31d08aaa6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.Select -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select(source, selector); - - // Act - var result = ArrayExtensions.Select((ReadOnlyMemory)source.AsMemory(), selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlySpan.Tests.cs deleted file mode 100644 index f127cfabf..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,26 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.Select -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select(source, selector); - - // Act - var result = ArrayExtensions.Select((ReadOnlySpan)source.AsSpan(), selector); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.Span.Tests.cs deleted file mode 100644 index 5c7b4658b..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.Span.Tests.cs +++ /dev/null @@ -1,26 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.Select -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select(source, selector); - - // Act - var result = ArrayExtensions.Select(source.AsSpan(), selector); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ValueEnumerable.Tests.cs deleted file mode 100644 index c6e8b6bb6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ValueEnumerable.Tests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.Select -{ - public class ValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var wrapped = Wrap.AsValueEnumerable(source); - var expected = - System.Linq.Enumerable.Select(wrapped, selector); - - // Act - var result = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ValueReadOnlyCollection.Tests.cs deleted file mode 100644 index 308d3dfd3..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ValueReadOnlyCollection.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.Select -{ - public class ValueReadOnlyCollectionTests - { - [Theory] - [MemberData(nameof(TestData.SelectorEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyCollection(source); - var expected = - System.Linq.Enumerable.Select(wrapped, selector); - - // Act - var result = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.Array.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.Array.Tests.cs deleted file mode 100644 index 9005acd6f..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.Array.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectAt -{ - public class ArrayTests - { - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector); - - // Act - var result = source.AsValueEnumerable() - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.AsyncValueEnumerable.Tests.cs deleted file mode 100644 index 112ade684..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.AsyncValueEnumerable.Tests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectAt -{ - public class AsyncValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Select_Selector_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var wrapped = Wrap.AsAsyncValueEnumerable(source); - var expected = System.Linq.Enumerable - .Select(source, selector); - - // Act - var result = AsyncValueEnumerableExtensions - .Select, Wrap.AsyncEnumerator, int, string>(wrapped, selector.AsAsync()); - - // Assert - _ = result.Must() - .BeAsyncEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.Memory.Tests.cs deleted file mode 100644 index dd17239d0..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.Memory.Tests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectIndex -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select(source, selector); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyList.Tests.cs deleted file mode 100644 index 441888732..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectAt -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = - System.Linq.Enumerable.Select(wrapped, selector); - - // Act - var result = wrapped.AsValueEnumerable() - .Select(selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 1b4fff20d..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectIndex -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select(source, selector); - - // Act - var result = ArrayExtensions.Select((ReadOnlyMemory)source.AsMemory(), selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlySpan.Tests.cs deleted file mode 100644 index 5d2752085..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,27 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectIndex -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select(source, selector); - - // Act - var result = ArrayExtensions.Select((ReadOnlySpan)source.AsSpan(), selector); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.Span.Tests.cs deleted file mode 100644 index 9272e52f6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.Span.Tests.cs +++ /dev/null @@ -1,26 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectIndex -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var expected = - System.Linq.Enumerable.Select(source, selector); - - // Act - var result = ArrayExtensions.Select(source.AsSpan(), selector); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ValueEnumerable.Tests.cs deleted file mode 100644 index 68cfc0ce2..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ValueEnumerable.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Net.Security; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectAt -{ - public class ValueEnumerableTests - { - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var wrapped = Wrap.AsValueEnumerable(source); - var expected = - System.Linq.Enumerable.Select(wrapped, selector); - - // Act - var result = ValueEnumerableExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ValueReadOnlyCollection.Tests.cs deleted file mode 100644 index 045d4fc12..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ValueReadOnlyCollection.Tests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectAt -{ - public class ValueReadOnlyCollectionTests - { - [Theory] - [MemberData(nameof(TestData.SelectorAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SelectorAtMultiple), MemberType = typeof(TestData))] - public void Select_With_ValidData_Must_Succeed(int[] source, Func selector) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyCollection(source); - var expected = - System.Linq.Enumerable.Select(wrapped, selector); - - // Act - var result = ValueReadOnlyCollectionExtensions - .Select, Wrap.Enumerator, int, string>(wrapped, selector); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector.TestData.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector.TestData.cs deleted file mode 100644 index 2d7d70d6b..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector.TestData.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Numerics; -using Xunit; - -namespace NetFabric.Hyperlinq -{ - public static partial class TestData - { - - public static TheoryData, Vector>, Func> SelectVector => - new TheoryData, Vector>, Func> - { - { new int[] { }, item => item * 2, item => item * 2 }, - { new int[] { 0, }, item => item * 2, item => item * 2 }, - { new int[] { 0, 1}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2, 3}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2, 3, 4}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2, 3, 4, 5}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, item => item * 2, item => item * 2 }, - { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}, item => item * 2, item => item * 2 }, - }; - - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector/SelectVector.ArraySegment.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector/SelectVector.ArraySegment.cs deleted file mode 100644 index 9740944fa..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector/SelectVector.ArraySegment.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using System.Numerics; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectVector -{ - public class ArraySegmentTests - { - [Theory] - [MemberData(nameof(TestData.SelectVector), MemberType = typeof(TestData))] - public void SelectVector_ToArray_With_ValidData_Must_Succeed(int[] source, Func, Vector> vectorSelector, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - var result = new ArraySegment(source).AsValueEnumerable() - .SelectVector(vectorSelector, selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector/SelectVector.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector/SelectVector.ReadOnlyMemory.Tests.cs deleted file mode 100644 index a029130b6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectVector/SelectVector.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using System.Numerics; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Projection.SelectVector -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.SelectVector), MemberType = typeof(TestData))] - public void SelectVector_ToArray_With_ValidData_Must_Succeed(int[] source, Func, Vector> vectorSelector, Func selector) - { - // Arrange - var expected = Enumerable - .Select(source, selector) - .ToArray(); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .SelectVector(vectorSelector, selector) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ArraySegment.Tests.cs deleted file mode 100644 index 7db8bac47..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ArraySegment.Tests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.All -{ - public class ArraySegmentTests - { - [Fact] - public void All_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - - // Act - var result = source.AsValueEnumerable() - .All(_ => true); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void All_Predicate_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .All(wrapped, predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void All_Skip_Take_PredicateAt_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate) - .Count() == count; - - // Act - var result = wrapped.AsValueEnumerable() - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.Memory.Tests.cs deleted file mode 100644 index c9447bfe1..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.Memory.Tests.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.All -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void All_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = System.Linq.Enumerable.All(source, predicate); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void All_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) == source.Length; - - // Act - var result = source.AsMemory().AsValueEnumerable() - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ReadOnlyList.Tests.cs deleted file mode 100644 index efb8ce228..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,103 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.All -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void All_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var expected = - System.Linq.Enumerable.All(wrapped, predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void All_Skip_Take_Predicate_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var expected = - System.Linq.Enumerable.All( - System.Linq.Enumerable.Take( - System.Linq.Enumerable.Skip(source, skip), take), predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void All_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) == source.Length; - - // Act - var result = wrapped.AsValueEnumerable() - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void All_Skip_Take_PredicateAt_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var count = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Take( - System.Linq.Enumerable.Skip(source, skip), take)); - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where( - System.Linq.Enumerable.Take( - System.Linq.Enumerable.Skip(source, skip), take), predicate)) == count; - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 401341db1..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.All -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void All_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = System.Linq.Enumerable.All(source, predicate); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void All_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) == source.Length; - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .All(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ReadOnlySpan.Tests.cs deleted file mode 100644 index 73a039f37..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.All -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void All_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = System.Linq.Enumerable.All(source, predicate); - - // Act - var result = ArrayExtensions - .All((ReadOnlySpan)source.AsSpan(), predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void All_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) == source.Length; - - // Act - var result = ArrayExtensions - .All((ReadOnlySpan)source.AsSpan(), predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.Span.Tests.cs deleted file mode 100644 index 002c501b8..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/All/All.Span.Tests.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.All -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void All_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = System.Linq.Enumerable.All(source, predicate); - - // Act - var result = ArrayExtensions - .All(source.AsSpan(), predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void All_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) == source.Length; - - // Act - var result = ArrayExtensions - .All(source.AsSpan(), predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ArraySegment.Tests.cs deleted file mode 100644 index ef7ee42bf..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ArraySegment.Tests.cs +++ /dev/null @@ -1,106 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any -{ - public class ArraySegmentTests - { - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Any_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Any(wrapped); - - // Act - var result = wrapped.AsValueEnumerable() - .Any(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Fact] - public void Any_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - - // Act - var result = source.AsValueEnumerable() - .Any(); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Fact] - public void Any_Predicate_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - var expected = Enumerable.Empty(); - - // Act - var result = source.AsValueEnumerable() - .Any(_ => true); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Any(wrapped, predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Any(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void Any_PredicateAt_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = Enumerable - .Where(wrapped, predicate) - .Count() != 0; - - // Act - var result = wrapped.AsValueEnumerable() - .Any(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ReadOnlyList.Tests.cs deleted file mode 100644 index 22c1993b3..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Any_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var expected = - System.Linq.Enumerable.Any(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Any(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Any_Skip_Take_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var expected = - System.Linq.Enumerable.Any( - System.Linq.Enumerable.Take( - System.Linq.Enumerable.Skip(source, skip), take)); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Any(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var expected = - System.Linq.Enumerable.Any(wrapped, predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Any(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateMultiple), MemberType = typeof(TestData))] - public void Any_Skip_Take_Predicate_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var expected = - System.Linq.Enumerable.Any( - System.Linq.Enumerable.Take( - System.Linq.Enumerable.Skip(source, skip), take), predicate); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Any(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Any_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var expected = - System.Linq.Enumerable.Any( - System.Linq.Enumerable.Where(source, predicate)); - - // Act - var result = wrapped.AsValueEnumerable() - .Any(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakePredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakePredicateAtMultiple), MemberType = typeof(TestData))] - public void Any_Skip_Take_PredicateAt_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyList(source); - var expected = - System.Linq.Enumerable.Any( - System.Linq.Enumerable.Where( - System.Linq.Enumerable.Take( - System.Linq.Enumerable.Skip( - source, skip), take), predicate)); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Any(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 3322ebf42..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any -{ - public class ReadOnlyMemoryTests - { - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Any_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = - System.Linq.Enumerable.Any(source); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Any(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Any(source, predicate); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Any(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Any_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) != 0; - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Any(predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ReadOnlySpan.Tests.cs deleted file mode 100644 index 475da4dbf..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any -{ - public class ReadOnlySpanTests - { - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Any_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = - System.Linq.Enumerable.Any(source); - - // Act - var result = ArrayExtensions - .Any((ReadOnlySpan)source.AsSpan()); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Any(source, predicate); - - // Act - var result = ArrayExtensions - .Any((ReadOnlySpan)source.AsSpan(), predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Any_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) != 0; - - // Act - var result = ArrayExtensions - .Any((ReadOnlySpan)source.AsSpan(), predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.Span.Tests.cs deleted file mode 100644 index ad67ef412..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.Span.Tests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using NetFabric.Assertive; -using System; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any -{ - public class SpanTests - { - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Any_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = - System.Linq.Enumerable.Any(source); - - // Act - var result = ArrayExtensions - .Any(source.AsSpan()); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Any(source, predicate); - - // Act - var result = ArrayExtensions - .Any(source.AsSpan(), predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Any_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) != 0; - - // Act - var result = ArrayExtensions - .Any(source.AsSpan(), predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ValueReadOnlyCollection.Tests.cs deleted file mode 100644 index f8952ed3c..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Any/Any.ValueReadOnlyCollection.Tests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Any -{ - public class ValueReadOnlyCollectionTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Any_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyCollection(source); - var expected = - System.Linq.Enumerable.Any(source); - - // Act - var result = ValueReadOnlyCollectionExtensions - .Any, Wrap.Enumerator, int>(wrapped); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] - public void Any_Predicate_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyCollection(source); - var expected = - System.Linq.Enumerable.Any(wrapped, predicate); - - // Act - var result = ValueReadOnlyCollectionExtensions - .Any, Wrap.Enumerator, int>(wrapped, predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] - public void Any_PredicateAt_With_ValidData_Must_Succeed(int[] source, Func predicate) - { - // Arrange - var wrapped = Wrap.AsValueReadOnlyCollection(source); - var expected = - System.Linq.Enumerable.Count( - System.Linq.Enumerable.Where(source, predicate)) != 0; - - // Act - var result = ValueReadOnlyCollectionExtensions - .Any, Wrap.Enumerator, int>(wrapped, predicate); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ArraySegment.Tests.cs deleted file mode 100644 index 7438f65f1..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ArraySegment.Tests.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Contains -{ - public class ArraySegmentTests - { - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var value = int.MaxValue; - - // Act - var result = ArrayExtensions - .Contains(wrapped, value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Fact] - public void Contains_With_NullArray_Must_Succeed() - { - // Arrange - var source = default(ArraySegment); - - // Act - var result = ArrayExtensions - .Contains(source, 0); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source.Select(item => item.ToString()).ToArray(), offset, count); - var value = default(string); - - // Act - var result = ArrayExtensions - .Contains(wrapped, value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var value = wrapped.Last(); - - // Act - var result = ArrayExtensions - .Contains(wrapped, value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source.Select(item => item.ToString()).ToArray(), offset, count); - var value = wrapped.Last().ToString(); - - // Act - var result = ArrayExtensions - .Contains(wrapped, value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var value = int.MaxValue; - - // Act - var result = ArrayExtensions - .Contains(wrapped, value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var value = wrapped.Last(); - - // Act - var result = ArrayExtensions - .Contains(wrapped, value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var value = int.MaxValue; - - // Act - var result = ArrayExtensions - .Contains(wrapped, value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_Contains_Must_ReturnTrue(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var value = wrapped.Last(); - - // Act - var result = ArrayExtensions - .Contains(wrapped, value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.Memory.Tests.cs deleted file mode 100644 index b55634b1f..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.Memory.Tests.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Contains -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = default(string); - var referenceSource = source.Select(item => item.ToString()).ToArray(); - - // Act - var result = referenceSource.AsMemory().AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = Enumerable.Last(source); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = Enumerable.Last(source).ToString(); - var referenceSource = source.Select(item => item.ToString()).ToArray(); - - // Act - var result = referenceSource.AsMemory().AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Contains(value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = Enumerable.Last(source); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Contains(value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Contains(value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = Enumerable.Last(source); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Contains(value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ReadOnlyList.Tests.cs deleted file mode 100644 index 319bfad44..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,256 +0,0 @@ -using System; -using System.Collections.Generic; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Contains -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = default(string); - var wrapped = Wrap.AsValueReadOnlyList(source.AsValueEnumerable().Select(item => item.ToString()).ToArray()); - - // Act - var result = wrapped.AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source); - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source).ToString(); - var wrapped = Wrap.AsValueReadOnlyList(source.AsValueEnumerable().Select(item => item.ToString()).ToArray()); - - // Act - var result = wrapped.AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Contains(value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source); - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Contains(value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeTrue(); - } - - //////////////////// - // Skip Take - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_Skip_Take_With_Null_And_NotContains_Must_ReturnFalse(int[] source, int skip, int take) - { - // Arrange - var value = int.MaxValue; - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Contains(value, null); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_Skip_Take_With_Null_And_Contains_Must_ReturnTrue(int[] source, int skip, int take) - { - // Arrange - var value = - System.Linq.Enumerable.Last( - System.Linq.Enumerable.Take( - System.Linq.Enumerable.Skip(source, skip), take)); - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Contains(value, null); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_Skip_Take_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source, int skip, int take) - { - // Arrange - var value = int.MaxValue; - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Contains(value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_Skip_Take_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source, int skip, int take) - { - // Arrange - var value = - System.Linq.Enumerable.Last( - System.Linq.Enumerable.Take( - System.Linq.Enumerable.Skip(source, skip), take)); - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Contains(value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_Skip_Take_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source, int skip, int take) - { - // Arrange - var value = int.MaxValue; - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Contains(value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Contains_Skip_Take_With_Comparer_And_Contains_Must_ReturnTrue(int[] source, int skip, int take) - { - // Arrange - var value = - System.Linq.Enumerable.Last( - System.Linq.Enumerable.Take( - System.Linq.Enumerable.Skip(source, skip), take)); - var wrapped = Wrap.AsValueReadOnlyList(source); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Contains(value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 3504a5239..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Contains -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = default(string); - var wrapped = source.Select(item => item.ToString()).ToArray(); - - // Act - var result = ((ReadOnlyMemory)wrapped.AsMemory()).AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = Enumerable.Last(source); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = Enumerable.Last(source).ToString(); - var wrapped = source.Select(item => item.ToString()).ToArray(); - - // Act - var result = ((ReadOnlyMemory)wrapped.AsMemory()).AsValueEnumerable() - .Contains(value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Contains(value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = Enumerable.Last(source); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Contains(value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Contains(value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = Enumerable.Last(source); - - // Act - var result = ((ReadOnlyMemory)source.AsMemory()).AsValueEnumerable() - .Contains(value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ReadOnlySpan.Tests.cs deleted file mode 100644 index 6530a8896..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.ReadOnlySpan.Tests.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Contains -{ - public class ReadOnlySpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = ArrayExtensions - .Contains((ReadOnlySpan)source.AsSpan(), value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = default(string); - var wrapped = source.AsValueEnumerable().Select(item => item.ToString()).ToArray(); - - // Act - var result = ArrayExtensions - .Contains((ReadOnlySpan)wrapped.AsSpan(), value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source); - - // Act - var result = ArrayExtensions - .Contains((ReadOnlySpan)source.AsSpan(), value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source).ToString(); - var wrapped = source.AsValueEnumerable().Select(item => item.ToString()).ToArray(); - - // Act - var result = ArrayExtensions - .Contains((ReadOnlySpan)wrapped.AsSpan(), value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = ArrayExtensions - .Contains((ReadOnlySpan)source.AsSpan(), value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source); - - // Act - var result = ArrayExtensions - .Contains((ReadOnlySpan)source.AsSpan(), value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = ArrayExtensions - .Contains((ReadOnlySpan)source.AsSpan(), value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source); - - // Act - var result = ArrayExtensions - .Contains((ReadOnlySpan)source.AsSpan(), value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.Span.Tests.cs deleted file mode 100644 index 63d1563d7..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Quantifier/Contains/Contains.Span.Tests.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; -using NetFabric.Assertive; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Quantifier.Contains -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = ArrayExtensions - .Contains(source.AsSpan(), value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = default(string); - var wrapped = source.AsValueEnumerable().AsValueEnumerable().Select(item => item.ToString()).ToArray(); - - // Act - var result = ArrayExtensions - .Contains(wrapped.AsSpan(), value); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ValueType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source); - - // Act - var result = ArrayExtensions - .Contains(source.AsSpan(), value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_ReferenceType_With_Null_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source).ToString(); - var wrapped = source.AsValueEnumerable().Select(item => item.ToString()).ToArray(); - - // Act - var result = ArrayExtensions - .Contains(wrapped.AsSpan(), value); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = ArrayExtensions - .Contains(source.AsSpan(), value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_DefaultComparer_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source); - - // Act - var result = ArrayExtensions - .Contains(source.AsSpan(), value, EqualityComparer.Default); - - // Assert - _ = result.Must() - .BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_NotContains_Must_ReturnFalse(int[] source) - { - // Arrange - var value = int.MaxValue; - - // Act - var result = ArrayExtensions - .Contains(source.AsSpan(), value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeFalse(); - } - - [Theory] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Contains_With_Comparer_And_Contains_Must_ReturnTrue(int[] source) - { - // Arrange - var value = System.Linq.Enumerable.Last(source); - - // Act - var result = ArrayExtensions - .Contains(source.AsSpan(), value, TestComparer.Instance); - - // Assert - _ = result.Must() - .BeTrue(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.Memory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.Memory.Tests.cs deleted file mode 100644 index 3c2e8d81b..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.Memory.Tests.cs +++ /dev/null @@ -1,97 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Buffers; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct -{ - public class MemoryTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = - System.Linq.Enumerable.Distinct(source); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Distinct(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = - System.Linq.Enumerable.ToArray( - System.Linq.Enumerable.Distinct(source)); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Distinct() - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = - System.Linq.Enumerable.ToArray( - System.Linq.Enumerable.Distinct(source)); - - // Act - using var result = source.AsMemory().AsValueEnumerable() - .Distinct() - .ToArray(pool); - - // Assert - _ = result - .SequenceEqual(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = - System.Linq.Enumerable.ToList( - System.Linq.Enumerable.Distinct(source)); - - // Act - var result = source.AsMemory().AsValueEnumerable() - .Distinct() - .ToList(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyList.Tests.cs deleted file mode 100644 index d2d1c4d25..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyList.Tests.cs +++ /dev/null @@ -1,117 +0,0 @@ -using NetFabric.Assertive; -using System.Buffers; -using System.ComponentModel; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct -{ - public class ReadOnlyListTests - { - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Distinct_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Distinct(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Distinct(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Distinct() - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Distinct() - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var pool = MemoryPool.Shared; - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Distinct() - .ToArray(); - - // Act - using var result = wrapped.AsValueEnumerable() - .Skip(skip) - .Take(take) - .Distinct() - .ToArray(pool); - - // Assert - _ = result - .SequenceEqual(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap.AsReadOnlyList(source); - var expected = Enumerable - .Skip(source, skip) - .Take(take) - .Distinct() - .ToList(); - - // Act - var result = wrapped - .Skip(skip) - .Take(take) - .Distinct() - .ToList(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs deleted file mode 100644 index 7172f9f44..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs +++ /dev/null @@ -1,97 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Buffers; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct -{ - public class ReadOnlyMemoryTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = - System.Linq.Enumerable.Distinct(source); - - // Act - var result = ArrayExtensions - .Distinct((ReadOnlyMemory)source.AsMemory()); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = - System.Linq.Enumerable.ToArray( - System.Linq.Enumerable.Distinct(source)); - - // Act - var result = ArrayExtensions - .Distinct((ReadOnlyMemory)source.AsMemory()) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = - System.Linq.Enumerable.ToArray( - System.Linq.Enumerable.Distinct(source)); - - // Act - using var result = ArrayExtensions - .Distinct((ReadOnlyMemory)source.AsMemory()) - .ToArray(pool); - - // Assert - _ = result - .SequenceEqual(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = - System.Linq.Enumerable.ToList( - System.Linq.Enumerable.Distinct(source)); - - // Act - var result = ArrayExtensions - .Distinct((ReadOnlyMemory)source.AsMemory()) - .ToList(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.Span.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.Span.Tests.cs deleted file mode 100644 index 84b40c0f5..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.Span.Tests.cs +++ /dev/null @@ -1,95 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Buffers; -using System.Linq; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct -{ - public class SpanTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .Distinct(source); - - // Act - var result = ArrayExtensions - .Distinct(source.AsSpan()); - - // Assert - _ = result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .Distinct(source) - .ToArray(); - - // Act - var result = ArrayExtensions - .Distinct(source.AsSpan()) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var pool = MemoryPool.Shared; - var expected = Enumerable - .Distinct(source) - .ToArray(); - - // Act - var result = ArrayExtensions - .Distinct(source.AsSpan()) - .ToArray(pool); - - // Assert - _ = result.Memory - .SequenceEqual(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var expected = Enumerable - .Distinct(source) - .ToList(); - - // Act - var result = ArrayExtensions - .Distinct(source.AsSpan()) - .ToList(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsEnumerable.TestEnumerableWithValueTypeEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsEnumerable.TestEnumerableWithValueTypeEnumerator.cs new file mode 100644 index 000000000..c5d1c5ad6 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsEnumerable.TestEnumerableWithValueTypeEnumerator.cs @@ -0,0 +1,43 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_> AsValueEnumerable(this TestEnumerableWithValueTypeEnumerator source) + // => new(source, source); + + //public readonly struct AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_ + // : IValueEnumerable.Enumerator> + // where TEnumerable : IEnumerable + //{ + // readonly TestEnumerableWithValueTypeEnumerator source; + // readonly TEnumerable source2; + + // internal AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_(TestEnumerableWithValueTypeEnumerator source, TEnumerable source2) + // => (this.source, this.source2) = (source, source2); + + // // Implement IValueEnumerable.Enumerator> + + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public TestEnumerableWithValueTypeEnumerator.Enumerator GetEnumerator() => source.GetEnumerator(); + + // IEnumerator IEnumerable.GetEnumerator() => source2.GetEnumerator(); + + // IEnumerator IEnumerable.GetEnumerator() => source2.GetEnumerator(); + //} + + public static GeneratedExtensionMethods.AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_ AsEnumerable(this GeneratedExtensionMethods.AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_ source) + => NetFabric.Hyperlinq.ValueEnumerableExtensions.AsEnumerable.Enumerator, TestValueType>(source); +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.IReadOnlyList.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.IReadOnlyList.cs new file mode 100644 index 000000000..fc53886f4 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.IReadOnlyList.cs @@ -0,0 +1,133 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_System_Collections_Generic_IReadOnlyList_TestValueType_ AsValueEnumerable(this System.Collections.Generic.IReadOnlyList source) + => new(source); + + public readonly struct AsValueEnumerable_System_Collections_Generic_IReadOnlyList_TestValueType_ + : IValueReadOnlyList>, IList + { + readonly System.Collections.Generic.IReadOnlyList source; + + internal AsValueEnumerable_System_Collections_Generic_IReadOnlyList_TestValueType_(System.Collections.Generic.IReadOnlyList source) + => this.source = source; + + // Implement IValueEnumerable> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerator GetEnumerator() => new(source.GetEnumerator()); + + IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator(); + + // Implement ICollection + + public int Count => source.Count; + + public bool IsReadOnly => true; + + void ICollection.Add(TestValueType item) => throw new NotSupportedException(); + + bool ICollection.Remove(TestValueType item) => throw new NotSupportedException(); + + void ICollection.Clear() => throw new NotSupportedException(); + + public bool Contains(TestValueType item) + { + if (Count is 0) + return false; + + if (source is ICollection collection) + return collection.Contains(item); + + using var enumerator = GetEnumerator(); + while (enumerator.MoveNext()) + { + if (EqualityComparer.Default.Equals(enumerator.Current, item)) + return true; + } + return false; + } + + public void CopyTo(TestValueType[] array, int arrayIndex) + { + if (Count is 0) + return; + + if (array.Length - arrayIndex < Count) + throw new ArgumentException("Destination array was not long enough. Check the destination index, length, and the array's lower bounds.", nameof(array)); + + if (source is ICollection collection) + { + collection.CopyTo(array, arrayIndex); + return; + } + + using var enumerator = GetEnumerator(); + if (arrayIndex is 0 && array.Length == Count) + { + for (var index = 0; index < array.Length && enumerator.MoveNext(); index++) + array[index] = enumerator.Current; + } + else + { + checked + { + for (var index = arrayIndex; enumerator.MoveNext(); index++) + array[index] = enumerator.Current; + } + } + } + + // Implement IList + + public TestValueType this[int index] => source[index]; + + TestValueType IList.this[int index] + { + get => source[index]; + set => throw new NotSupportedException(); + } + + void IList.Insert(int index, TestValueType item) => throw new NotSupportedException(); + + void IList.RemoveAt(int index) => throw new NotSupportedException(); + + public int IndexOf(TestValueType item) + { + if (Count is not 0) + { + if (source is IList list) + return list.IndexOf(item); + + checked + { + var index = 0; + foreach (var current in source) + { + if (EqualityComparer.Default.Equals(current, item)) + return index; + + index++; + } + } + } + return -1; + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.Repeat.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.Repeat.cs new file mode 100644 index 000000000..0c28f1d9f --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.Repeat.cs @@ -0,0 +1,20 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static NetFabric.Hyperlinq.ValueEnumerable.RepeatEnumerable AsValueEnumerable(this NetFabric.Hyperlinq.ValueEnumerable.RepeatEnumerable source) + => source; +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestCollection.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestCollection.cs new file mode 100644 index 000000000..b7dd4b562 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestCollection.cs @@ -0,0 +1,56 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestCollection_TestValueType_ AsValueEnumerable(this TestCollection source) + => new(source); + + public readonly struct AsValueEnumerable_TestCollection_TestValueType_ + : IValueReadOnlyCollection.Enumerator>, ICollection + { + readonly TestCollection source; + + internal AsValueEnumerable_TestCollection_TestValueType_(TestCollection source) + => this.source = source; + + // Implement IValueEnumerable.Enumerator> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TestCollection.Enumerator GetEnumerator() => source.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + // Implement ICollection + + public int Count => source.Count; + + public bool IsReadOnly => true; + + void ICollection.Add(TestValueType item) => throw new NotSupportedException(); + + bool ICollection.Remove(TestValueType item) => throw new NotSupportedException(); + + void ICollection.Clear() => throw new NotSupportedException(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(TestValueType item) => source.Contains(item); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(TestValueType[] array, int arrayIndex) => source.CopyTo(array, arrayIndex); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs new file mode 100644 index 000000000..8b7764809 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs @@ -0,0 +1,62 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_ AsValueEnumerable(this TestEnumerableWithInterfacelessPublicEnumerator source) + => new(source); + + public readonly struct AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_ + : IValueEnumerable + { + readonly TestEnumerableWithInterfacelessPublicEnumerator source; + + internal AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_(TestEnumerableWithInterfacelessPublicEnumerator source) + => this.source = source; + + // Implement IValueEnumerable + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() => new(source.GetEnumerator()); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator : IEnumerator + { + readonly TestEnumerableWithInterfacelessPublicEnumerator.Enumerator source; + + internal Enumerator(TestEnumerableWithInterfacelessPublicEnumerator.Enumerator source) + => this.source = source; + + public TestValueType Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source.Current; + } + + object? IEnumerator.Current => source.Current; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() => source.MoveNext(); + + public void Reset() => throw new NotSupportedException(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() { } + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs new file mode 100644 index 000000000..ac52dc301 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs @@ -0,0 +1,62 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_ AsValueEnumerable(this TestEnumerableWithNoInterfaces source) + => new(source); + + public readonly struct AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_ + : IValueEnumerable + { + readonly TestEnumerableWithNoInterfaces source; + + internal AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_(TestEnumerableWithNoInterfaces source) + => this.source = source; + + // Implement IValueEnumerable + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() => new(source.GetEnumerator()); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator : IEnumerator + { + readonly TestEnumerableWithNoInterfaces.Enumerator source; + + internal Enumerator(TestEnumerableWithNoInterfaces.Enumerator source) + => this.source = source; + + public TestValueType Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source.Current; + } + + object? IEnumerator.Current => source.Current; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() => source.MoveNext(); + + public void Reset() => throw new NotSupportedException(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() { } + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs new file mode 100644 index 000000000..13eca99d5 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs @@ -0,0 +1,63 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose_TestValueType_ AsValueEnumerable(this TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose source) + => new(source); + + public readonly struct AsValueEnumerable_TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose_TestValueType_ + : IValueEnumerable + { + readonly TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose source; + + internal AsValueEnumerable_TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose_TestValueType_(TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose source) + => this.source = source; + + // Implement IValueEnumerable + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() => new(source.GetEnumerator()); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator : IEnumerator + { + readonly TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.Enumerator source; + + internal Enumerator(TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.Enumerator source) + => this.source = source; + + public TestValueType Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => source.Current; + } + + object? IEnumerator.Current => source.Current; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() => source.MoveNext(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Reset() => source.Reset(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() => source.Dispose(); + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs new file mode 100644 index 000000000..407d1fa67 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs @@ -0,0 +1,38 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestEnumerableWithReferenceTypeEnumerator_TestValueType_ AsValueEnumerable(this TestEnumerableWithReferenceTypeEnumerator source) + => new(source); + + public readonly struct AsValueEnumerable_TestEnumerableWithReferenceTypeEnumerator_TestValueType_ + : IValueEnumerable> + { + readonly TestEnumerableWithReferenceTypeEnumerator source; + + internal AsValueEnumerable_TestEnumerableWithReferenceTypeEnumerator_TestValueType_(TestEnumerableWithReferenceTypeEnumerator source) + => this.source = source; + + // Implement IValueEnumerable> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerator GetEnumerator() => new(source.GetEnumerator()); + + IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator(); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs new file mode 100644 index 000000000..2e787b696 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs @@ -0,0 +1,38 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_ AsValueEnumerable(this TestEnumerableWithValueTypeEnumerator source) + => new(source); + + public readonly struct AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_ + : IValueEnumerable.Enumerator> + { + readonly TestEnumerableWithValueTypeEnumerator source; + + internal AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_(TestEnumerableWithValueTypeEnumerator source) + => this.source = source; + + // Implement IValueEnumerable.Enumerator> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TestEnumerableWithValueTypeEnumerator.Enumerator GetEnumerator() => source.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestList.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestList.cs new file mode 100644 index 000000000..fcbae6d1f --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestList.cs @@ -0,0 +1,73 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestList_TestValueType_ AsValueEnumerable(this TestList source) + => new(source); + + public readonly struct AsValueEnumerable_TestList_TestValueType_ + : IValueReadOnlyList.Enumerator>, IList + { + readonly TestList source; + + internal AsValueEnumerable_TestList_TestValueType_(TestList source) + => this.source = source; + + // Implement IValueEnumerable.Enumerator> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TestList.Enumerator GetEnumerator() => source.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + // Implement ICollection + + public int Count => source.Count; + + public bool IsReadOnly => true; + + void ICollection.Add(TestValueType item) => throw new NotSupportedException(); + + bool ICollection.Remove(TestValueType item) => throw new NotSupportedException(); + + void ICollection.Clear() => throw new NotSupportedException(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(TestValueType item) => source.Contains(item); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(TestValueType[] array, int arrayIndex) => source.CopyTo(array, arrayIndex); + + // Implement IList + + public TestValueType this[int index] => source[index]; + + TestValueType IList.this[int index] + { + get => source[index]; + set => throw new NotSupportedException(); + } + + void IList.Insert(int index, TestValueType item) => throw new NotSupportedException(); + + void IList.RemoveAt(int index) => throw new NotSupportedException(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int IndexOf(TestValueType item) => source.IndexOf(item); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestListWithExplicitInterfaces.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestListWithExplicitInterfaces.cs new file mode 100644 index 000000000..c1a97176e --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestListWithExplicitInterfaces.cs @@ -0,0 +1,87 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestListWithExplicitInterfaces_TestValueType_> AsValueEnumerable(this TestListWithExplicitInterfaces source) + => new(source); + + public readonly struct AsValueEnumerable_TestListWithExplicitInterfaces_TestValueType_ + : IValueReadOnlyList>, IList + where TEnumerable : IList + { + readonly TEnumerable source; + + internal AsValueEnumerable_TestListWithExplicitInterfaces_TestValueType_(TEnumerable source) + => this.source = source; + + // Implement IValueEnumerable> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ValueEnumerator GetEnumerator() => new(source.GetEnumerator()); + + IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator(); + + // Implement ICollection + + public int Count => source.Count; + + public bool IsReadOnly => true; + + void ICollection.Add(TestValueType item) => throw new NotSupportedException(); + + bool ICollection.Remove(TestValueType item) => throw new NotSupportedException(); + + void ICollection.Clear() => throw new NotSupportedException(); + + public void CopyTo(Span span) + { + if (Count is 0) return; + if (span.Length < Count) throw new ArgumentException("Destination span was not long enough.", nameof(span)); + + var index = 0; + foreach (var current in this) + { + span[index] = current; + checked { index++; } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(TestValueType item) => source.Contains(item); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(TestValueType[] array, int arrayIndex) => source.CopyTo(array, arrayIndex); + + // Implement IList + + public TestValueType this[int index] => source[index]; + + TestValueType IList.this[int index] + { + get => source[index]; + set => throw new NotSupportedException(); + } + + void IList.Insert(int index, TestValueType item) => throw new NotSupportedException(); + + void IList.RemoveAt(int index) => throw new NotSupportedException(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int IndexOf(TestValueType item) => source.IndexOf(item); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestReadOnlyCollection.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestReadOnlyCollection.cs new file mode 100644 index 000000000..a1e9b7b6c --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestReadOnlyCollection.cs @@ -0,0 +1,88 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestReadOnlyCollection_TestValueType_ AsValueEnumerable(this TestReadOnlyCollection source) + => new(source); + + public readonly struct AsValueEnumerable_TestReadOnlyCollection_TestValueType_ + : IValueReadOnlyCollection.Enumerator>, ICollection + { + readonly TestReadOnlyCollection source; + + internal AsValueEnumerable_TestReadOnlyCollection_TestValueType_(TestReadOnlyCollection source) + => this.source = source; + + // Implement IValueEnumerable.Enumerator> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TestReadOnlyCollection.Enumerator GetEnumerator() => source.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + // Implement ICollection + + public int Count => source.Count; + + public bool IsReadOnly => true; + + void ICollection.Add(TestValueType item) => throw new NotSupportedException(); + + bool ICollection.Remove(TestValueType item) => throw new NotSupportedException(); + + void ICollection.Clear() => throw new NotSupportedException(); + + public bool Contains(TestValueType item) + { + if (Count is 0) + return false; + + using var enumerator = GetEnumerator(); + while (enumerator.MoveNext()) + { + if (EqualityComparer.Default.Equals(enumerator.Current, item)) + return true; + } + return false; + } + + public void CopyTo(TestValueType[] array, int arrayIndex) + { + if (Count is 0) + return; + + if (array.Length - arrayIndex < Count) + throw new ArgumentException("Destination array was not long enough. Check the destination index, length, and the array's lower bounds.", nameof(array)); + + using var enumerator = GetEnumerator(); + if (arrayIndex is 0 && array.Length == Count) + { + for (var index = 0; index < array.Length && enumerator.MoveNext(); index++) + array[index] = enumerator.Current; + } + else + { + checked + { + for (var index = arrayIndex; enumerator.MoveNext(); index++) + array[index] = enumerator.Current; + } + } + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestReadOnlyList.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestReadOnlyList.cs new file mode 100644 index 000000000..2aa13a609 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestReadOnlyList.cs @@ -0,0 +1,121 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AsValueEnumerable_TestReadOnlyList_TestValueType_ AsValueEnumerable(this TestReadOnlyList source) + => new(source); + + public readonly struct AsValueEnumerable_TestReadOnlyList_TestValueType_ + : IValueReadOnlyList.Enumerator>, IList + { + readonly TestReadOnlyList source; + + internal AsValueEnumerable_TestReadOnlyList_TestValueType_(TestReadOnlyList source) + => this.source = source; + + // Implement IValueEnumerable.Enumerator> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TestReadOnlyList.Enumerator GetEnumerator() => source.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + // Implement ICollection + + public int Count => source.Count; + + public bool IsReadOnly => true; + + void ICollection.Add(TestValueType item) => throw new NotSupportedException(); + + bool ICollection.Remove(TestValueType item) => throw new NotSupportedException(); + + void ICollection.Clear() => throw new NotSupportedException(); + + public bool Contains(TestValueType item) + { + if (Count is 0) + return false; + + using var enumerator = GetEnumerator(); + while (enumerator.MoveNext()) + { + if (EqualityComparer.Default.Equals(enumerator.Current, item)) + return true; + } + return false; + } + + public void CopyTo(TestValueType[] array, int arrayIndex) + { + if (Count is 0) + return; + + if (array.Length - arrayIndex < Count) + throw new ArgumentException("Destination array was not long enough. Check the destination index, length, and the array's lower bounds.", nameof(array)); + + using var enumerator = GetEnumerator(); + if (arrayIndex is 0 && array.Length == Count) + { + for (var index = 0; index < array.Length && enumerator.MoveNext(); index++) + array[index] = enumerator.Current; + } + else + { + checked + { + for (var index = arrayIndex; enumerator.MoveNext(); index++) + array[index] = enumerator.Current; + } + } + } + + // Implement IList + + public TestValueType this[int index] => source[index]; + + TestValueType IList.this[int index] + { + get => source[index]; + set => throw new NotSupportedException(); + } + + void IList.Insert(int index, TestValueType item) => throw new NotSupportedException(); + + void IList.RemoveAt(int index) => throw new NotSupportedException(); + + public int IndexOf(TestValueType item) + { + if (Count is not 0) + { + checked + { + var index = 0; + foreach (var current in source) + { + if (EqualityComparer.Default.Equals(current, item)) + return index; + + index++; + } + } + } + return -1; + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestValueEnumerable.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestValueEnumerable.cs new file mode 100644 index 000000000..c3f0ec230 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/AsValueEnumerable.TestValueEnumerable.cs @@ -0,0 +1,20 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TestValueEnumerable AsValueEnumerable(this TestValueEnumerable source) + => source; +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/Count.Array.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Count.Array.cs new file mode 100644 index 000000000..a640141f5 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Count.Array.cs @@ -0,0 +1,20 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(this NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable source, System.Func predicate) + => NetFabric.Hyperlinq.ValueReadOnlyListExtensions.Count, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, TestValueType, NetFabric.Hyperlinq.FunctionWrapper>(source, predicate); +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/Count.Span.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Count.Span.cs new file mode 100644 index 000000000..53c5b7c63 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Count.Span.cs @@ -0,0 +1,20 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(this NetFabric.Hyperlinq.ArrayExtensions.SpanValueEnumerable source, Func predicate) + => NetFabric.Hyperlinq.ArrayExtensions.Count(source.Span, predicate); +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/Empty.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Empty.cs new file mode 100644 index 000000000..dbe7e1354 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Empty.cs @@ -0,0 +1,16 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/Select.Array.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Select.Array.cs new file mode 100644 index 000000000..af70ff565 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Select.Array.cs @@ -0,0 +1,20 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static NetFabric.Hyperlinq.ValueReadOnlyListExtensions.SelectEnumerable, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, TestValueType, TestReferenceType, NetFabric.Hyperlinq.FunctionWrapper> Select(this NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable source, System.Func selector) + => NetFabric.Hyperlinq.ValueReadOnlyListExtensions.Select, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, TestValueType, TestReferenceType>(source, selector); +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/Select.TestEnumerableWithValueTypeEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Select.TestEnumerableWithValueTypeEnumerator.cs new file mode 100644 index 000000000..2410968fe --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Select.TestEnumerableWithValueTypeEnumerator.cs @@ -0,0 +1,45 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + //[MethodImpl(MethodImplOptions.AggressiveInlining)] + //public static AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_> AsValueEnumerable(this TestEnumerableWithValueTypeEnumerator source) + // => new(source, source); + + //public readonly struct AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_ + // : IValueEnumerable.Enumerator> + // where TEnumerable : IEnumerable + //{ + // readonly TestEnumerableWithValueTypeEnumerator source; + // readonly TEnumerable source2; + + // internal AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_(TestEnumerableWithValueTypeEnumerator source, TEnumerable source2) + // => (this.source, this.source2) = (source, source2); + + // // Implement IValueEnumerable.Enumerator> + + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // public TestEnumerableWithValueTypeEnumerator.Enumerator GetEnumerator() => source.GetEnumerator(); + + // IEnumerator IEnumerable.GetEnumerator() => source2.GetEnumerator(); + + // IEnumerator IEnumerable.GetEnumerator() => source2.GetEnumerator(); + //} + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueEnumerableExtensions.SelectEnumerable.Enumerator, TestValueType, TestReferenceType, NetFabric.Hyperlinq.FunctionWrapper> Select(this GeneratedExtensionMethods.AsValueEnumerable_TestEnumerableWithValueTypeEnumerator_TestValueType_ source, System.Func selector) + => NetFabric.Hyperlinq.ValueEnumerableExtensions.Select.Enumerator, TestValueType, TestReferenceType, NetFabric.Hyperlinq.FunctionWrapper>(source, selector); +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/Skip.Take.Array.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Skip.Take.Array.cs new file mode 100644 index 000000000..b26994268 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Skip.Take.Array.cs @@ -0,0 +1,24 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static NetFabric.Hyperlinq.ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, TestValueType> Skip(this NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable source, int count) + => NetFabric.Hyperlinq.ValueReadOnlyListExtensions.Skip, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, TestValueType>(source, count); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static NetFabric.Hyperlinq.ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, TestValueType> Take(this NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable source, int count) + => NetFabric.Hyperlinq.ValueReadOnlyCollectionExtensions.Take, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, TestValueType>(source, count); +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Results/Where.Array.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Where.Array.cs new file mode 100644 index 000000000..e3626ae0d --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Results/Where.Array.cs @@ -0,0 +1,20 @@ +#nullable enable + +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq; + +static partial class GeneratedExtensionMethods +{ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static NetFabric.Hyperlinq.ValueReadOnlyCollectionExtensions.WhereEnumerable, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, TestValueType, NetFabric.Hyperlinq.FunctionWrapper> Where(this NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable source, System.Func selector) + => NetFabric.Hyperlinq.ValueReadOnlyListExtensions.Where, NetFabric.Hyperlinq.ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, TestValueType, NetFabric.Hyperlinq.FunctionWrapper>(source, selector); +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsEnumerable.TestEnumerableWithValueTypeEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsEnumerable.TestEnumerableWithValueTypeEnumerator.cs new file mode 100644 index 000000000..c95d5f829 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsEnumerable.TestEnumerableWithValueTypeEnumerator.cs @@ -0,0 +1,13 @@ +using System; +using System.Linq; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void Count_TestEnumerableWithValueTypeEnumerator() + { + _ = new TestEnumerableWithValueTypeEnumerator() + .AsValueEnumerable() + .AsEnumerable(); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Empty.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Empty.cs new file mode 100644 index 000000000..0b0b74e93 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Empty.cs @@ -0,0 +1,28 @@ +using System; +//using NetFabric.Hyperlinq; => DO NOT UNCOMMENT + +partial class TestsSource +{ + static void AsValueEnumerable_Empty() + { + // test calling AsValueEnumerable() for types that don't need source generation + // with NetFabric.Hyperlinq namespace NOT in a using clause + +#if !NOT_TESTING + var array = Array.Empty(); + + _ = array.AsValueEnumerable(); + _ = new ArraySegment(array).AsValueEnumerable(); + + _ = array.AsMemory().AsValueEnumerable(); + _ = ((ReadOnlyMemory)array.AsMemory()).AsValueEnumerable(); + + _ = array.AsSpan().AsValueEnumerable(); + _ = ((ReadOnlySpan)array.AsSpan()).AsValueEnumerable(); + + var list = new List(); + _ = list.AsValueEnumerable(); +#endif + } +} + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Empty2.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Empty2.cs new file mode 100644 index 000000000..6c0371f60 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Empty2.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using NetFabric.Hyperlinq; // namespace is known at compile time + +partial class TestsSource +{ + static void AsValueEnumerable_Empty2() + { + // test calling AsValueEnumerable() for types that don't need source generation + + var array = Array.Empty(); + + _ = array.AsValueEnumerable(); + _ = ArrayExtensions.AsValueEnumerable(array); + _ = new ArraySegment(array).AsValueEnumerable(); + + _ = array.AsMemory().AsValueEnumerable(); + _ = ((ReadOnlyMemory)array.AsMemory()).AsValueEnumerable(); + + _ = array.AsSpan().AsValueEnumerable(); + _ = ((ReadOnlySpan)array.AsSpan()).AsValueEnumerable(); + + var list = new List(); + _ = list.AsValueEnumerable(); + } +} + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Empty3.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Empty3.cs new file mode 100644 index 000000000..d7d379d2c --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Empty3.cs @@ -0,0 +1,18 @@ +using System; +using System.Linq; +using NetFabric.Hyperlinq; // namespace is known at compile time + +partial class TestsSource +{ + static void AsValueEnumerable_Empty3() + { + var valueEnumerable = Array + .Empty() + .AsValueEnumerable(); + + _ = Enumerable.Count(valueEnumerable); + _ = Enumerable.Count(valueEnumerable, _ => true); + _ = Enumerable.Take(Enumerable.Skip(valueEnumerable, 1), 2); + } +} + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.IReadOnlyList.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.IReadOnlyList.cs new file mode 100644 index 000000000..33b500a91 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.IReadOnlyList.cs @@ -0,0 +1,17 @@ +using NetFabric.Hyperlinq; +using System.Collections.Generic; + +partial class TestsSource +{ + static void AsValueEnumerable_IReadOnlyList() + { + // test calling AsValueEnumerable() on an IReadOnlyList<> + IReadOnlyList list = new TestReadOnlyList(); + _ = list.AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Repeat.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Repeat.cs new file mode 100644 index 000000000..834978c04 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.Repeat.cs @@ -0,0 +1,13 @@ +using System; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_Repeat() + { + // test calling AsValueEnumerable() for types that implement IValueEnumerable<,> + + _ = ValueEnumerable.Repeat(0, 100).AsValueEnumerable(); + } +} + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestCollection.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestCollection.cs new file mode 100644 index 000000000..c66f27f10 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestCollection.cs @@ -0,0 +1,15 @@ +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_Collection() + { + // test calling AsValueEnumerable() on an implementation of ICollection<> + _ = new TestCollection().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs new file mode 100644 index 000000000..d9734c3b4 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator() + { + // test calling AsValueEnumerable() for types that implement IEnumerable<> + // but the public GetEnumerator() returns a type that doesn't implement IEnumerator<> + + _ = new TestEnumerableWithInterfacelessPublicEnumerator().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs new file mode 100644 index 000000000..12071aee1 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_TestEnumerableWithNoInterfaces() + { + // test calling AsValueEnumerable() for types that do not implement IEnumerable<> + // but the public GetEnumerator() returns a type that doesn't implement IEnumerator<> + + _ = new TestEnumerableWithNoInterfaces().AsValueEnumerable(); + } +} + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs new file mode 100644 index 000000000..7554e76fe --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose() + { + // test calling AsValueEnumerable() for types that do not implement IEnumerable<> + // and the public GetEnumerator() returns a type that implement IDisposable and has a Reset() method + + _ = new TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs new file mode 100644 index 000000000..304df9a9d --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_TestEnumerableWithReferenceTypeEnumerator() + { + // test calling AsValueEnumerable() for types that implement IEnumerable<> and the enumerator is not a value type + + _ = new TestEnumerableWithReferenceTypeEnumerator().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs new file mode 100644 index 000000000..1ff2412ec --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_EnumerableWithValueTypeEnumerator() + { + // test calling AsValueEnumerable() for types that implement IEnumerable<> and the enumerator is a value type + + _ = new TestEnumerableWithValueTypeEnumerator().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestList.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestList.cs new file mode 100644 index 000000000..f1421d0ab --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestList.cs @@ -0,0 +1,15 @@ +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_List() + { + // test calling AsValueEnumerable() on an implementation of IList<> + _ = new TestList().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestListWithExplicitInterfaces.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestListWithExplicitInterfaces.cs new file mode 100644 index 000000000..72d84d63f --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestListWithExplicitInterfaces.cs @@ -0,0 +1,15 @@ +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_ReadOnlyListWithExplicitInterfaces() + { + // test calling AsValueEnumerable() on an IValueEnumerable + _ = new TestListWithExplicitInterfaces().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestReadOnlyCollection.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestReadOnlyCollection.cs new file mode 100644 index 000000000..15c9cce44 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestReadOnlyCollection.cs @@ -0,0 +1,15 @@ +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_ReadOnlyCollection() + { + // test calling AsValueEnumerable() on an IValueEnumerable + _ = new TestReadOnlyCollection().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestReadOnlyList.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestReadOnlyList.cs new file mode 100644 index 000000000..cb02ca0d8 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestReadOnlyList.cs @@ -0,0 +1,15 @@ +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_ReadOnlyList() + { + // test calling AsValueEnumerable() on an IValueEnumerable + _ = new TestReadOnlyList().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestValueEnumerable.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestValueEnumerable.cs new file mode 100644 index 000000000..fbb432ef8 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/AsValueEnumerable.TestValueEnumerable.cs @@ -0,0 +1,15 @@ +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void AsValueEnumerable_ValueEnumerable() + { + // test calling AsValueEnumerable() on an IValueEnumerable + _ = new TestValueEnumerable().AsValueEnumerable(); + } +} + + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/Common/Enumerables.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Common/Enumerables.cs new file mode 100644 index 000000000..283f0f9df --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Common/Enumerables.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +public class TestEnumerableWithNoInterfaces +{ + public Enumerator GetEnumerator() + => new(); + + public readonly struct Enumerator + { + public T Current + => default!; + + public bool MoveNext() + => false; + } +} + +public class TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose +{ + public Enumerator GetEnumerator() + => new(); + + public readonly struct Enumerator + : IDisposable + { + public T Current + => default!; + + public bool MoveNext() + => false; + + public void Reset() + { } + + public void Dispose() + { } + } +} + +public readonly struct TestEnumerableWithInterfacelessPublicEnumerator + : IEnumerable +{ + public Enumerator GetEnumerator() + => new(); + IEnumerator IEnumerable.GetEnumerator() + => new DisposableEnumerator(); + IEnumerator IEnumerable.GetEnumerator() + => new DisposableEnumerator(); + + public struct Enumerator + { + public T Current + => default!; + + public bool MoveNext() + => false; + } + + class DisposableEnumerator + : IEnumerator + { + public T Current + => default!; + object? IEnumerator.Current + => default; + + public bool MoveNext() + => false; + + public void Reset() + { } + public void Dispose() + { } + } +} + +public readonly struct TestEnumerableWithValueTypeEnumerator + : IEnumerable +{ + public Enumerator GetEnumerator() + => new(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + + public readonly struct Enumerator + : IEnumerator + { + public T Current + => default!; + object? IEnumerator.Current + => default; + + public bool MoveNext() + => false; + + public void Reset() + { } + public void Dispose() + { } + } +} + + +public readonly struct TestEnumerableWithReferenceTypeEnumerator + : IEnumerable +{ + public IEnumerator GetEnumerator() + => new Enumerator(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + + class Enumerator + : IEnumerator + { + public T Current + => default!; + object? IEnumerator.Current + => default; + + public bool MoveNext() + => false; + + public void Reset() + { } + public void Dispose() + { } + } +} + +public readonly struct TestReadOnlyCollection + : IReadOnlyCollection +{ + public int Count => default; + + public Enumerator GetEnumerator() + => new(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + + public readonly struct Enumerator + : IEnumerator + { + public T Current + => default!; + object? IEnumerator.Current + => default; + + public bool MoveNext() + => false; + + public void Reset() + { } + public void Dispose() + { } + } +} + +public readonly struct TestCollection + : ICollection +{ + public int Count => default; + + public bool IsReadOnly => true; + public bool Contains(T item) => default; + public void CopyTo(T[] array, int arrayIndex) { } + void ICollection.Add(T item) => throw new NotSupportedException(); + bool ICollection.Remove(T item) => throw new NotSupportedException(); + void ICollection.Clear() => throw new NotSupportedException(); + + public Enumerator GetEnumerator() + => new(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + + public readonly struct Enumerator + : IEnumerator + { + public T Current + => default!; + object? IEnumerator.Current + => default; + + public bool MoveNext() + => false; + + public void Reset() + { } + public void Dispose() + { } + } +} + +public readonly struct TestReadOnlyList + : IReadOnlyList +{ + public int Count => default; + + public T this[int index] => default!; + + public Enumerator GetEnumerator() + => new(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + + public readonly struct Enumerator + : IEnumerator + { + public T Current + => default!; + object? IEnumerator.Current + => default; + + public bool MoveNext() + => false; + + public void Reset() + { } + public void Dispose() + { } + } +} + +public readonly struct TestList + : IList +{ + public int Count => default; + + public bool IsReadOnly => true; + + public T this[int index] + { + get => default!; + set => throw new NotSupportedException(); + } + + public bool Contains(T item) => default; + public void CopyTo(T[] array, int arrayIndex) { } + void ICollection.Add(T item) => throw new NotSupportedException(); + bool ICollection.Remove(T item) => throw new NotSupportedException(); + void ICollection.Clear() => throw new NotSupportedException(); + + public int IndexOf(T item) => -1; + void IList.Insert(int index, T item) => throw new NotSupportedException(); + void IList.RemoveAt(int index) => throw new NotSupportedException(); + + public Enumerator GetEnumerator() + => new(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + + public readonly struct Enumerator + : IEnumerator + { + public T Current + => default!; + object? IEnumerator.Current + => default; + + public bool MoveNext() + => false; + + public void Reset() + { } + public void Dispose() + { } + } +} + + +public readonly struct TestListWithExplicitInterfaces + : IList +{ + int ICollection.Count => default; + + bool ICollection.IsReadOnly => true; + + T IList.this[int index] + { + get => default!; + set => throw new NotSupportedException(); + } + + bool ICollection.Contains(T item) => default; + void ICollection.CopyTo(T[] array, int arrayIndex) { } + void ICollection.Add(T item) => throw new NotSupportedException(); + bool ICollection.Remove(T item) => throw new NotSupportedException(); + void ICollection.Clear() => throw new NotSupportedException(); + + int IList.IndexOf(T item) => -1; + void IList.Insert(int index, T item) => throw new NotSupportedException(); + void IList.RemoveAt(int index) => throw new NotSupportedException(); + + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + IEnumerator IEnumerable.GetEnumerator() + => new Enumerator(); + + class Enumerator + : IEnumerator + { + T IEnumerator.Current + => default!; + object? IEnumerator.Current + => default; + + bool IEnumerator.MoveNext() + => false; + + void IEnumerator.Reset() + { } + void IDisposable.Dispose() + { } + } +} + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/Common/ItemTypes.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Common/ItemTypes.cs new file mode 100644 index 000000000..1249d551d --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Common/ItemTypes.cs @@ -0,0 +1,7 @@ +public struct TestValueType +{ +} + +public class TestReferenceType +{ +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/Common/ValueEnumerables.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Common/ValueEnumerables.cs new file mode 100644 index 000000000..0819feb46 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Common/ValueEnumerables.cs @@ -0,0 +1,45 @@ +using NetFabric.Hyperlinq; +using System.Collections; +using System.Collections.Generic; + +public class TestValueEnumerable + : IValueEnumerable.DisposableEnumerator> +{ + public Enumerator GetEnumerator() + => new(); + + DisposableEnumerator IValueEnumerable.GetEnumerator() + => new(); + + IEnumerator IEnumerable.GetEnumerator() + => new DisposableEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => new DisposableEnumerator(); + + public readonly struct Enumerator + { + public T Current + => default!; + + public bool MoveNext() + => false; + } + + public readonly struct DisposableEnumerator + : IEnumerator + { + public T Current + => default!; + object? IEnumerator.Current + => default; + + public bool MoveNext() + => false; + + public void Reset() + { } + public void Dispose() + { } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/Count.Array.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Count.Array.cs new file mode 100644 index 000000000..59af328dd --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Count.Array.cs @@ -0,0 +1,13 @@ +using System; +using System.Linq; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void Count_ArraySegmentValueEnumerable() + { + _ = Array.Empty() + .AsValueEnumerable() + .Count(_ => true); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/Count.Span.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Count.Span.cs new file mode 100644 index 000000000..fc14b2aab --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Count.Span.cs @@ -0,0 +1,16 @@ +using System; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void Count_SpanValueEnumerable() + { +#if !NOT_TESTING + _ = Array.Empty().AsSpan() + .AsValueEnumerable() + .Count(_ => true); +#endif + } +} + + diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/Select.Array.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Select.Array.cs new file mode 100644 index 000000000..3fd1cfea8 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Select.Array.cs @@ -0,0 +1,13 @@ +using System; +using System.Linq; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void Select_ArraySegmentValueEnumerable() + { + _ = Array.Empty() + .AsValueEnumerable() + .Select(_ => new TestReferenceType()); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/Select.TestEnumerableWithValueTypeEnumerator.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Select.TestEnumerableWithValueTypeEnumerator.cs new file mode 100644 index 000000000..32fd6358f --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Select.TestEnumerableWithValueTypeEnumerator.cs @@ -0,0 +1,13 @@ +using System; +using System.Linq; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void Select_TestEnumerableWithValueTypeEnumerator() + { + _ = new TestEnumerableWithValueTypeEnumerator() + .AsValueEnumerable() + .Select(_ => new TestReferenceType()); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/Skip.Take.Array.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Skip.Take.Array.cs new file mode 100644 index 000000000..346966ae9 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Skip.Take.Array.cs @@ -0,0 +1,14 @@ +using System; +using System.Linq; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void Skip_Take_ArraySegmentValueEnumerable() + { + _ = Array.Empty() + .AsValueEnumerable() + .Skip(1) + .Take(2); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/Source/Where.Array.cs b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Where.Array.cs new file mode 100644 index 000000000..3062e609b --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/TestData/Source/Where.Array.cs @@ -0,0 +1,13 @@ +using System; +using System.Linq; +using NetFabric.Hyperlinq; + +partial class TestsSource +{ + static void Where_ArraySegmentValueEnumerable() + { + _ = Array.Empty() + .AsValueEnumerable() + .Where(_ => true); + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/TestData.Empty.cs b/NetFabric.Hyperlinq.UnitTests/TestData/TestData.Empty.cs deleted file mode 100644 index 9340f5dd7..000000000 --- a/NetFabric.Hyperlinq.UnitTests/TestData/TestData.Empty.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System; -using Xunit; - -namespace NetFabric.Hyperlinq -{ - public static partial class TestData - { - public static TheoryData Empty => - new TheoryData - { - { new int[] { } }, - }; - - public static TheoryData SkipEmpty => - new TheoryData - { - { new int[] { }, -1 }, - { new int[] { }, 0 }, - { new int[] { }, 1 }, - - { new int[] { 1 }, 1 }, - { new int[] { 1 }, 5 }, - - { new int[] { 0, 1, 2 }, 3 }, - { new int[] { 0, 1, 2 }, 5 }, - }; - - public static TheoryData TakeEmpty => - new TheoryData - { - { new int[] { }, -1 }, - { new int[] { }, 0 }, - { new int[] { }, 1 }, - - { new int[] { 5 }, -1 }, - { new int[] { 5 }, 0 }, - - { new int[] { 0, 1, 2, 3, 4, 5 }, -1 }, - { new int[] { 0, 1, 2, 3, 4, 5 }, 0 }, - }; - - public static TheoryData SkipTakeEmpty => - new TheoryData - { - { new int[] { }, -1, -1 }, - { new int[] { }, -1, 0 }, - { new int[] { }, 0, -1 }, - { new int[] { }, 0, 0 }, - { new int[] { }, 0, 9 }, - { new int[] { }, 1, 0 }, - { new int[] { }, 1, 9 }, - - { new int[] { 1 }, -1, -1 }, - { new int[] { 1 }, -1, 0 }, - { new int[] { 1 }, 0, -1 }, - { new int[] { 1 }, 0, 0 }, - { new int[] { 1 }, 1, 0 }, - { new int[] { 1 }, 1, 9 }, - - { new int[] { 1, 2, 3, 4, 5 }, -1, -1 }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 0 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, -1 }, - { new int[] { 1, 2, 3, 4, 5 }, 2, -1 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 0 }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 0 }, - { new int[] { 1, 2, 3, 4, 5 }, 9, 0 }, - { new int[] { 1, 2, 3, 4, 5 }, 9, 9 }, - }; - - public static TheoryData> PredicateEmpty => - new TheoryData> - { - { new int[] { }, _ => false }, - { new int[] { }, _ => true }, - - { new int[] { 1 }, _ => false }, - { new int[] { 1 }, item => item > 9 }, - - { new int[] { 1, 2, 3, 4, 5 }, _ => false }, - { new int[] { 1, 2, 3, 4, 5 }, item => item > 9 }, - }; - - public static TheoryData> SkipTakePredicateEmpty => - new TheoryData> - { - { new int[] { }, 0, 9, _ => false }, - { new int[] { }, 0, 0, _ => true }, - { new int[] { }, 0, 9, item => item > 9 }, - - { new int[] { 1 }, 0, 0, _ => true }, - { new int[] { 1 }, 9, 9, _ => true }, - { new int[] { 1 }, 0, 9, _ => false }, - { new int[] { 1 }, 0, 9, item => item > 9 }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 0, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 9, 9, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => false }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item > 9 }, - }; - - public static TheoryData, Func> PredicatePredicateEmpty => - new TheoryData, Func> - { - { new int[] { }, _ => true, _ => true }, - - { new int[] { 1, 2, 3, 4, 5 }, _ => false, _ => false }, - { new int[] { 1, 2, 3, 4, 5 }, _ => true, _ => false }, - { new int[] { 1, 2, 3, 4, 5 }, _ => false, _ => true }, - }; - - public static TheoryData, Func> SkipTakePredicatePredicateEmpty => - new TheoryData, Func> - { - { new int[] { }, 0, 9, _ => true, _ => true }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => false, _ => false }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, _ => false }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => false, _ => true }, - }; - - public static TheoryData> PredicateAtEmpty => - new TheoryData> - { - { new int[] { }, (_, __) => false }, - { new int[] { }, (_, __) => true }, - - { new int[] { 1 }, (_, __) => false }, - { new int[] { 1 }, (item, _) => item > 9 }, - { new int[] { 1 }, (_, index) => index > 9 }, - - { new int[] { 1, 2, 3, 4, 5 }, (_, __) => false }, - { new int[] { 1, 2, 3, 4, 5 }, (item, _) => item > 9 }, - { new int[] { 1, 2, 3, 4, 5 }, (_, index) => index > 9 }, - }; - - public static TheoryData> SkipTakePredicateAtEmpty => - new TheoryData> - { - { new int[] { }, 0, 9, (_, __) => false }, - { new int[] { }, 0, 0, (_, __) => true }, - { new int[] { }, 0, 9, (item, _) => item > 9 }, - { new int[] { }, 0, 9, (_, index) => index > 9 }, - - { new int[] { 1 }, 0, 0, (_, __) => true }, - { new int[] { 1 }, 0, 9, (_, __) => false }, - { new int[] { 1 }, 0, 9, (item, _) => item > 9 }, - { new int[] { 1 }, 0, 9, (_, index) => index > 9 }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 0, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (_, __) => false }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (item, _) => item > 9 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (_, index) => index > 9 }, - - { new int[] { 1, 2, 3, 4, 5 }, 2, 0, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, (_, __) => false }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, (item, _) => item > 9 }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, (_, index) => index > 9 }, - }; - - public static TheoryData> SelectorEmpty => - new TheoryData> - { - { new int[] { }, item => item.ToString() }, - }; - - public static TheoryData> SkipTakeSelectorEmpty => - new TheoryData> - { - { new int[] { }, 0, 0, item => item.ToString() }, - { new int[] { }, 0, 9, item => item.ToString() }, - - { new int[] { 1 }, 0, 0, item => item.ToString() }, - { new int[] { 1 }, 9, 9, item => item.ToString() }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 0, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 9, 9, item => item.ToString() }, - }; - - public static TheoryData> SelectorAtEmpty => - new TheoryData> - { - { new int[] { }, (item, index) => $"{item} {index}" }, - }; - - public static TheoryData> SkipTakeSelectorAtEmpty => - new TheoryData> - { - { new int[] { }, 0, 0, (item, index) => $"{item} {index}" }, - { new int[] { }, 0, 9, (item, index) => $"{item} {index}" }, - - { new int[] { 1 }, 0, 0, (item, index) => $"{item} {index}" }, - { new int[] { 1 }, 9, 9, (item, index) => $"{item} {index}" }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 0, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, 9, 9, (item, index) => $"{item} {index}" }, - }; - - public static TheoryData, Func> PredicateSelectorEmpty => - new TheoryData, Func> - { - { new int[] { }, _ => false, item => item.ToString() }, - { new int[] { }, _ => true, item => item.ToString() }, - - { new int[] { 1 }, _ => false, item => item.ToString() }, - { new int[] { 1 }, item => item > 9, item => item.ToString() }, - - { new int[] { 1, 2, 3, 4, 5 }, _ => false, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, item => item > 9, item => item.ToString() }, - }; - - public static TheoryData, Func> SkipTakePredicateSelectorEmpty => - new TheoryData, Func> - { - { new int[] { }, 0, 9, _ => false, item => item.ToString() }, - { new int[] { }, 0, 0, _ => true, item => item.ToString() }, - { new int[] { }, 0, 9, item => item > 9, item => item.ToString() }, - - { new int[] { 1 }, 0, 0, _ => true, item => item.ToString() }, - { new int[] { 1 }, 9, 9, _ => true, item => item.ToString() }, - { new int[] { 1 }, 0, 9, _ => false, item => item.ToString() }, - { new int[] { 1 }, 0, 9, item => item > 9, item => item.ToString() }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 0, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 9, 9, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => false, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item > 9, item => item.ToString() }, - }; - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/TestData.Multiple.cs b/NetFabric.Hyperlinq.UnitTests/TestData/TestData.Multiple.cs deleted file mode 100644 index 35d83699e..000000000 --- a/NetFabric.Hyperlinq.UnitTests/TestData/TestData.Multiple.cs +++ /dev/null @@ -1,242 +0,0 @@ -using System; -using Xunit; - -namespace NetFabric.Hyperlinq -{ - public static partial class TestData - { - public static TheoryData Multiple => - new TheoryData - { - { new int[] { 1, 2, 3, 4, 5 } }, - }; - - public static TheoryData SkipMultiple => - new TheoryData - { - { new int[] { 1, 2, 3, 4, 5 }, -1 }, - { new int[] { 1, 2, 3, 4, 5 }, 0 }, - { new int[] { 1, 2, 3, 4, 5 }, 2 }, - }; - - public static TheoryData TakeMultiple => - new TheoryData - { - { new int[] { 1, 2, 3, 4, 5 }, 2 }, - { new int[] { 1, 2, 3, 4, 5 }, 5 }, - { new int[] { 1, 2, 3, 4, 5 }, 9 }, - }; - - public static TheoryData SkipTakeMultiple => - new TheoryData - { - { new int[] { 1, 2, 3, 4, 5 }, -1, 2 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 2 }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 2 }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 5 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 5 }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 3 }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 9 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9 }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9 }, - }; - - public static TheoryData> PredicateMultiple => - new TheoryData> - { - { new int[] { 1, 2, 3, 4, 5 }, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 1 }, - }; - - public static TheoryData> SkipTakePredicateMultiple => - new TheoryData> - { - { new int[] { 1, 2, 3, 4, 5 }, -1, 2, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 2, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 2, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 5, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 5, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 3, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 9, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, _ => true }, - - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, item => (item & 0x01) == 0 }, - - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, item => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, item => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, item => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, item => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, item => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, item => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, item => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, item => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, item => (item & 0x01) == 1 }, - }; - - - public static TheoryData, Func> PredicatePredicateMultiple => - new TheoryData, Func> - { - { new int[] { 1, 2, 3, 4, 5 }, _ => true, _ => true }, - - { new int[] { 1, 2, 3, 4, 5 }, _ => true, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 1, _ => true }, - }; - - public static TheoryData, Func> SkipTakePredicatePredicateMultiple => - new TheoryData, Func> - { - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, _ => true }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, item => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => (item & 0x01) == 1, _ => true }, - }; - - public static TheoryData> PredicateAtMultiple => - new TheoryData> - { - { new int[] { 1, 2, 3, 4, 5 }, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, (item, _) => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5 }, (item, _) => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5 }, (_, index) => (index & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5 }, (_, index) => (index & 0x01) == 1 }, - }; - - public static TheoryData> SkipTakePredicateAtMultiple => - new TheoryData> - { - { new int[] { 1, 2, 3, 4, 5 }, 0, 2, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 2, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 5, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 5, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 3, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 9, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, (_, __) => true }, - - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, (item, _) => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, (item, _) => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, (item, _) => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, (item, _) => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, (item, _) => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, (item, _) => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, (item, _) => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, (item, _) => (item & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, (item, _) => (item & 0x01) == 0 }, - - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, (item, _) => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, (item, _) => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, (item, _) => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, (item, _) => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, (item, _) => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, (item, _) => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, (item, _) => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, (item, _) => (item & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, (item, _) => (item & 0x01) == 1 }, - - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, (_, index) => (index & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, (_, index) => (index & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, (_, index) => (index & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, (_, index) => (index & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, (_, index) => (index & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, (_, index) => (index & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, (_, index) => (index & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, (_, index) => (index & 0x01) == 0 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, (_, index) => (index & 0x01) == 0 }, - - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 4, (_, index) => (index & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 4, (_, index) => (index & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 4, (_, index) => (index & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 9, (_, index) => (index & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 9, (_, index) => (index & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7, (_, index) => (index & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1, 20, (_, index) => (index & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 20, (_, index) => (index & 0x01) == 1 }, - { new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 20, (_, index) => (index & 0x01) == 1 }, - }; - - public static TheoryData> SelectorMultiple => - new TheoryData> - { - { new int[] { 1, 2, 3, 4, 5 }, item => item.ToString() }, - }; - - public static TheoryData> SkipTakeSelectorMultiple => - new TheoryData> - { - { new int[] { 1, 2, 3, 4, 5 }, -1, 2, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 2, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 2, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 5, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 5, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 3, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 9, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, item => item.ToString() }, - }; - - public static TheoryData> SelectorAtMultiple => - new TheoryData> - { - { new int[] { 1, 2, 3, 4, 5 }, (item, index) => $"{item} {index}" }, - }; - - public static TheoryData> SkipTakeSelectorAtMultiple => - new TheoryData> - { - { new int[] { 1, 2, 3, 4, 5 }, -1, 2, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 2, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 2, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 5, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 5, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 3, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 9, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, (item, index) => $"{item} {index}" }, - }; - - public static TheoryData, Func> PredicateSelectorMultiple => - new TheoryData, Func> - { - { new int[] { 1, 2, 3, 4, 5 }, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 0, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, item => (item & 0x01) == 1, item => item.ToString() }, - }; - - public static TheoryData, Func> SkipTakePredicateSelectorMultiple => - new TheoryData, Func> - { - { new int[] { 1, 2, 3, 4, 5 }, -1, 2, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 2, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 2, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 5, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 5, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 3, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 9, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, _ => true, item => item.ToString() }, - - { new int[] { 1, 2, 3, 4, 5 }, -1, 5, item => (item & 0x01) == 0, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 5, item => (item & 0x01) == 0, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 9, item => (item & 0x01) == 0, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => (item & 0x01) == 0, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 1, 9, item => (item & 0x01) == 0, item => item.ToString() }, - - { new int[] { 1, 2, 3, 4, 5 }, -1, 5, item => (item & 0x01) == 1, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 5, item => (item & 0x01) == 1, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, -1, 9, item => (item & 0x01) == 1, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => (item & 0x01) == 1, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 1, 9, item => (item & 0x01) == 1, item => item.ToString() }, - }; - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/TestData/TestData.Single.cs b/NetFabric.Hyperlinq.UnitTests/TestData/TestData.Single.cs deleted file mode 100644 index 8a8e234cf..000000000 --- a/NetFabric.Hyperlinq.UnitTests/TestData/TestData.Single.cs +++ /dev/null @@ -1,201 +0,0 @@ -using System; -using Xunit; - -namespace NetFabric.Hyperlinq -{ - public static partial class TestData - { - public static TheoryData Single => - new TheoryData - { - { new int[] { 1 } }, - }; - - public static TheoryData SkipSingle => - new TheoryData - { - { new int[] { 1 }, -1 }, - { new int[] { 1 }, 0 }, - - { new int[] { 0, 1, 2 }, 2 }, - }; - - public static TheoryData TakeSingle => - new TheoryData - { - { new int[] { 1 }, 1 }, - - { new int[] { 1, 2, 3, 4, 5 }, 1 }, - }; - - public static TheoryData SkipTakeSingle => - new TheoryData - { - { new int[] { 1 }, -1, 1 }, - { new int[] { 1 }, 0, 1 }, - - { new int[] { 1, 2, 3, 4, 5 }, -1, 1 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 1 }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 1 }, - { new int[] { 1, 2, 3, 4, 5 }, 4, 1 }, - }; - - public static TheoryData> PredicateSingle => - new TheoryData> - { - { new int[] { 1 }, _ => true }, - { new int[] { 1 }, item => item == 1 }, - - { new int[] { 1, 2, 3, 4, 5 }, item => item == 1 }, - { new int[] { 1, 2, 3, 4, 5 }, item => item == 3 }, - { new int[] { 1, 2, 3, 4, 5 }, item => item == 5 }, - }; - - public static TheoryData> SkipTakePredicateSingle => - new TheoryData> - { - { new int[] { 1 }, -1, 9, _ => true }, - { new int[] { 1 }, 0, 1, _ => true }, - { new int[] { 1 }, 0, 9, _ => true }, - { new int[] { 1 }, 0, 9, item => item == 1 }, - - { new int[] { 1, 2, 3, 4, 5 }, -1, 1, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 1, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 1, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 4, 1, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 1 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 3 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 5 }, - }; - - public static TheoryData, Func> PredicatePredicateSingle => - new TheoryData, Func> - { - { new int[] { 1 }, _ => true, _ => true }, - - { new int[] { 1, 2, 3, 4, 5 }, item => item == 3, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, _ => true, item => item == 3 }, - }; - - public static TheoryData, Func> SkipTakePredicatePredicateSingle => - new TheoryData, Func> - { - { new int[] { 1 }, 0, 9, _ => true, _ => true }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 3, _ => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, _ => true, item => item == 3 }, - }; - - public static TheoryData> PredicateAtSingle => - new TheoryData> - { - { new int[] { 1 }, (_, __) => true }, - { new int[] { 1 }, (item, _) => item == 1 }, - { new int[] { 1 }, (_, index) => index == 0 }, - - { new int[] { 1, 2, 3, 4, 5 }, (item, _) => item == 1 }, - { new int[] { 1, 2, 3, 4, 5 }, (item, _) => item == 3 }, - { new int[] { 1, 2, 3, 4, 5 }, (item, _) => item == 5 }, - { new int[] { 1, 2, 3, 4, 5 }, (_, index) => index == 0 }, - { new int[] { 1, 2, 3, 4, 5 }, (_, index) => index == 2 }, - { new int[] { 1, 2, 3, 4, 5 }, (_, index) => index == 4 }, - }; - - public static TheoryData> SkipTakePredicateAtSingle => - new TheoryData> - { - { new int[] { 1 }, -1, 1, (_, __) => true }, - { new int[] { 1 }, 0, 1, (_, __) => true }, - { new int[] { 1 }, 0, 1, (item, _) => item == 1 }, - { new int[] { 1 }, 0, 1, (_, index) => index == 0 }, - - { new int[] { 1 }, -1, 9, (_, __) => true }, - { new int[] { 1 }, 0, 9, (_, __) => true }, - { new int[] { 1 }, 0, 9, (item, _) => item == 1 }, - { new int[] { 1 }, 0, 9, (_, index) => index == 0 }, - - { new int[] { 1, 2, 3, 4, 5 }, -1, 1, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 1, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 1, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 4, 1, (_, __) => true }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (item, _) => item == 1 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (item, _) => item == 3 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (item, _) => item == 5 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (_, index) => index == 0 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (_, index) => index == 2 }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, (_, index) => index == 4 }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, (_, index) => index == 0 }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 9, (_, index) => index == 2 }, - }; - - public static TheoryData> SelectorSingle => - new TheoryData> - { - { new int[] { 1 }, item => item.ToString() }, - }; - - public static TheoryData> SkipTakeSelectorSingle => - new TheoryData> - { - { new int[] { 1 }, 0, 1, item => item.ToString() }, - - { new int[] { 1 }, -1, 9, item => item.ToString() }, - { new int[] { 1 }, 0, 9, item => item.ToString() }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 1, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 1, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 4, 1, item => item.ToString() }, - }; - - public static TheoryData> SelectorAtSingle => - new TheoryData> - { - { new int[] { 1 }, (item, index) => $"{item} {index}" }, - }; - - public static TheoryData> SkipTakeSelectorAtSingle => - new TheoryData> - { - { new int[] { 1 }, -1, 1, (item, index) => $"{item} {index}" }, - { new int[] { 1 }, 0, 1, (item, index) => $"{item} {index}" }, - - { new int[] { 1 }, -1, 9, (item, index) => $"{item} {index}" }, - { new int[] { 1 }, 0, 9, (item, index) => $"{item} {index}" }, - - { new int[] { 1, 2, 3, 4, 5 }, 0, 1, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 1, (item, index) => $"{item} {index}" }, - { new int[] { 1, 2, 3, 4, 5 }, 4, 1, (item, index) => $"{item} {index}" }, - }; - - public static TheoryData, Func> PredicateSelectorSingle => - new TheoryData, Func> - { - { new int[] { 1 }, _ => true, item => item.ToString() }, - { new int[] { 1 }, item => item == 1, item => item.ToString() }, - - { new int[] { 1, 2, 3, 4, 5 }, item => item == 1, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, item => item == 3, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, item => item == 5, item => item.ToString() }, - }; - - public static TheoryData, Func> SkipTakePredicateSelectorSingle => - new TheoryData, Func> - { - { new int[] { 1 }, -1, 1, _ => true, item => item.ToString() }, - { new int[] { 1 }, 0, 1, _ => true, item => item.ToString() }, - { new int[] { 1 }, 0, 1, item => item == 1, item => item.ToString() }, - - { new int[] { 1 }, -1, 9, _ => true, item => item.ToString() }, - { new int[] { 1 }, 0, 9, _ => true, item => item.ToString() }, - { new int[] { 1 }, 0, 9, item => item == 1, item => item.ToString() }, - - { new int[] { 1, 2, 3, 4, 5 }, -1, 1, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 1, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 2, 1, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 4, 1, _ => true, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 1, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 3, item => item.ToString() }, - { new int[] { 1, 2, 3, 4, 5 }, 0, 9, item => item == 5, item => item.ToString() }, - }; - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/SpanExtensions.cs b/NetFabric.Hyperlinq.UnitTests/Utils/SpanExtensions.cs deleted file mode 100644 index 6a1b2cdaa..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Utils/SpanExtensions.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Buffers; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq.UnitTests -{ - static class SpanExtensions - { - public static bool SequenceEqual(this IMemoryOwner first, IEnumerable second, IEqualityComparer comparer = null) - => SequenceEqual((ReadOnlySpan)first.Memory.Span, second, comparer); - - public static bool SequenceEqual(this Memory first, IEnumerable second, IEqualityComparer comparer = null) - => SequenceEqual((ReadOnlySpan)first.Span, second, comparer); - - public static bool SequenceEqual(this ReadOnlyMemory first, IEnumerable second, IEqualityComparer comparer = null) - => SequenceEqual(first.Span, second, comparer); - - public static bool SequenceEqual(this Span first, IEnumerable second, IEqualityComparer comparer = null) - => SequenceEqual((ReadOnlySpan)first, second, comparer); - - public static bool SequenceEqual(this ReadOnlySpan first, IEnumerable second, IEqualityComparer comparer = null) - { - comparer ??= EqualityComparer.Default; - - using var enumerator = second.GetEnumerator(); - for (var index = 0; true; index++) - { - var resultEnded = index == first.Length; - var expectedEnded = !enumerator.MoveNext(); - - if (resultEnded != expectedEnded) - return false; - - if (resultEnded) - return true; - - if (!comparer.Equals(first[index], enumerator.Current)) - return false; - } - } - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/TestComparer.cs b/NetFabric.Hyperlinq.UnitTests/Utils/TestComparer.cs deleted file mode 100644 index f702d0a0a..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Utils/TestComparer.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq.UnitTests -{ - class TestComparer : IEqualityComparer - { - TestComparer() { } - - public static TestComparer Instance { get; } = new TestComparer(); - - public bool Equals(T x, T y) - => EqualityComparer.Default.Equals(x, y); - - public int GetHashCode(T obj) - => EqualityComparer.Default.GetHashCode(obj); - } -} diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsAsyncEnumerable.cs b/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsAsyncEnumerable.cs deleted file mode 100644 index 4f57418de..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsAsyncEnumerable.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; - -namespace NetFabric.Hyperlinq -{ - public static partial class Wrap - { - public static AsyncEnumerableWrapper AsAsyncEnumerable(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); - - public readonly struct AsyncEnumerableWrapper - : IAsyncEnumerable - { - readonly T[] source; - - internal AsyncEnumerableWrapper(T[] source) - => this.source = source; - - public readonly AsyncEnumerator GetAsyncEnumerator() - => new AsyncEnumerator(source); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken _) - => new AsyncEnumerator(source); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsAsyncValueEnumerable.cs b/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsAsyncValueEnumerable.cs deleted file mode 100644 index 3e4f5ece8..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsAsyncValueEnumerable.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; - -namespace NetFabric.Hyperlinq -{ - public static partial class Wrap - { - public static AsyncValueEnumerableWrapper AsAsyncValueEnumerable(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); - - public readonly struct AsyncValueEnumerableWrapper - : IAsyncValueEnumerable> - { - readonly T[] source; - - internal AsyncValueEnumerableWrapper(T[] source) - => this.source = source; - - public readonly AsyncEnumerator GetAsyncEnumerator() - => new AsyncEnumerator(source); - readonly AsyncEnumerator IAsyncValueEnumerable>.GetAsyncEnumerator(CancellationToken _) - => new AsyncEnumerator(source); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken _) - => new AsyncEnumerator(source); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsEnumerable.cs b/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsEnumerable.cs deleted file mode 100644 index f210e7316..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsEnumerable.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class Wrap - { - public static EnumerableWrapper AsEnumerable(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); - - public class EnumerableWrapper - : IEnumerable - { - protected readonly T[] source; - - internal EnumerableWrapper(T[] source) - => this.source = source; - - public Enumerator GetEnumerator() - => new Enumerator(source); - IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueEnumerable.cs b/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueEnumerable.cs deleted file mode 100644 index 07d94b57a..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueEnumerable.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class Wrap - { - public static ValueEnumerableWrapper AsValueEnumerable(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); - - public readonly struct ValueEnumerableWrapper - : IValueEnumerable> - { - readonly T[] source; - - internal ValueEnumerableWrapper(T[] source) - => this.source = source; - - public readonly Enumerator GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyCollection.cs b/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyCollection.cs deleted file mode 100644 index 79225b9e3..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyCollection.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class Wrap - { - public static ValueReadOnlyCollectionWrapper AsValueReadOnlyCollection(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); - - public readonly struct ValueReadOnlyCollectionWrapper - : IValueReadOnlyCollection> - { - readonly T[] source; - - internal ValueReadOnlyCollectionWrapper(T[] source) - => this.source = source; - - public readonly int Count - => source.Length; - - public readonly Enumerator GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyList.cs b/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyList.cs deleted file mode 100644 index 709add857..000000000 --- a/NetFabric.Hyperlinq.UnitTests/Utils/Wrappers/Wrap.AsValueReadOnlyList.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace NetFabric.Hyperlinq -{ - public static partial class Wrap - { - public static ValueReadOnlyListWrapper AsValueReadOnlyList(T[] source) - => source is null - ? throw new ArgumentNullException(nameof(source)) - : new(source); - - public readonly struct ValueReadOnlyListWrapper - : IValueReadOnlyList> - { - readonly T[] source; - - internal ValueReadOnlyListWrapper(T[] source) - => this.source = source; - - public readonly int Count - => source.Length; - - public readonly T this[int index] - => source[index]; - - public readonly Enumerator GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - => new Enumerator(source); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Verifier.cs b/NetFabric.Hyperlinq.UnitTests/Verifier.cs new file mode 100644 index 000000000..102ea391c --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/Verifier.cs @@ -0,0 +1,49 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Text; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.IO; +using System.Linq; + +namespace NetFabric.Hyperlinq.SourceGenerator.UnitTests +{ + sealed class Verifier + { + static readonly string defaultFilePathPrefix = "Test"; + static readonly string testProjectName = "TestProject"; + + public static Project CreateProject(IEnumerable sources) + { + var projectId = ProjectId.CreateNewId(debugName: testProjectName); + + var coreLibPath = typeof(object).Assembly.Location; + var coreLibDirectory = Path.GetDirectoryName(coreLibPath)!; + var references = new[] { + MetadataReference.CreateFromFile(coreLibPath), + MetadataReference.CreateFromFile(Path.Combine(coreLibDirectory, "netstandard.dll")), + MetadataReference.CreateFromFile(Path.Combine(coreLibDirectory, "System.Runtime.dll")), + MetadataReference.CreateFromFile(Path.Combine(coreLibDirectory, "System.Collections.dll")), + MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location), + MetadataReference.CreateFromFile(typeof(ImmutableArray<>).Assembly.Location), + MetadataReference.CreateFromFile(typeof(IValueEnumerable<,>).Assembly.Location), + MetadataReference.CreateFromFile(typeof(ValueEnumerableExtensions).Assembly.Location), + }; + var solution = new AdhocWorkspace() + .CurrentSolution + .AddProject(projectId, testProjectName, testProjectName, LanguageNames.CSharp) + .AddMetadataReferences(projectId, references) + .WithProjectCompilationOptions(projectId, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + + var count = 0; + foreach (var source in sources) + { + var newFileName = defaultFilePathPrefix + count + ".cs"; + var documentId = DocumentId.CreateNewId(projectId, debugName: newFileName); + solution = solution.AddDocument(documentId, newFileName, SourceText.From(source)); + count++; + } + return solution.GetProject(projectId)!; + } + } +} diff --git a/NetFabric.Hyperlinq.sln b/NetFabric.Hyperlinq.sln index 4ac9d838d..ee9b89340 100644 --- a/NetFabric.Hyperlinq.sln +++ b/NetFabric.Hyperlinq.sln @@ -1,33 +1,34 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28516.95 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31423.177 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq", "NetFabric.Hyperlinq\NetFabric.Hyperlinq.csproj", "{EEEAA31B-434E-4849-A3E5-FA9664F5CE9B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq.UnitTests", "NetFabric.Hyperlinq.UnitTests\NetFabric.Hyperlinq.UnitTests.csproj", "{FE0CFD9E-7685-4595-8691-5364228722E9}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2C452DA5-FE07-451C-BFE1-AD14A57F7B09}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig .gitattributes = .gitattributes .gitignore = .gitignore + coverlet.runsettings = coverlet.runsettings Directory.Build.props = Directory.Build.props .github\workflows\dotnetcore.yml = .github\workflows\dotnetcore.yml global.json = global.json + Icon.png = Icon.png LICENSE = LICENSE NuGet.config = NuGet.config README.md = README.md - coverlet.runsettings = coverlet.runsettings EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq.Benchmarks", "NetFabric.Hyperlinq.Benchmarks\NetFabric.Hyperlinq.Benchmarks.csproj", "{02EE275F-6E2D-444A-AB1F-9BCD02DEA204}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq.SourceGenerator", "NetFabric.Hyperlinq.SourceGenerator\NetFabric.Hyperlinq.SourceGenerator.csproj", "{B8C004E3-F59E-4017-8781-C0F99B61BDEF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq.Abstractions", "NetFabric.Hyperlinq.Abstractions\NetFabric.Hyperlinq.Abstractions.csproj", "{6981E761-E698-437D-AF63-0E80844B7D41}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq.SourceGenerator.UnitTests", "NetFabric.Hyperlinq.SourceGenerator.UnitTests\NetFabric.Hyperlinq.SourceGenerator.UnitTests.csproj", "{12F96462-A2F8-4FBE-B4F5-29BA6A6DB4D9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq.Core", "NetFabric.Hyperlinq.Core\NetFabric.Hyperlinq.Core.csproj", "{9EA4EA87-7656-48BA-BE7F-E5CC1B48512D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq.Abstractions", "NetFabric.Hyperlinq.Abstractions\NetFabric.Hyperlinq.Abstractions.csproj", "{6981E761-E698-437D-AF63-0E80844B7D41}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq.Core.UnitTests", "NetFabric.Hyperlinq.Core.UnitTests\NetFabric.Hyperlinq.Core.UnitTests.csproj", "{794C4984-BB46-4A50-9BC1-53831B5C8002}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Hyperlinq.UnitTests", "NetFabric.Hyperlinq.UnitTests\NetFabric.Hyperlinq.UnitTests.csproj", "{F0A7B925-30F2-4FAA-97E6-7848B3E104B6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -39,26 +40,26 @@ Global {EEEAA31B-434E-4849-A3E5-FA9664F5CE9B}.Debug|Any CPU.Build.0 = Debug|Any CPU {EEEAA31B-434E-4849-A3E5-FA9664F5CE9B}.Release|Any CPU.ActiveCfg = Release|Any CPU {EEEAA31B-434E-4849-A3E5-FA9664F5CE9B}.Release|Any CPU.Build.0 = Release|Any CPU - {FE0CFD9E-7685-4595-8691-5364228722E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FE0CFD9E-7685-4595-8691-5364228722E9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FE0CFD9E-7685-4595-8691-5364228722E9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FE0CFD9E-7685-4595-8691-5364228722E9}.Release|Any CPU.Build.0 = Release|Any CPU {02EE275F-6E2D-444A-AB1F-9BCD02DEA204}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {02EE275F-6E2D-444A-AB1F-9BCD02DEA204}.Debug|Any CPU.Build.0 = Debug|Any CPU {02EE275F-6E2D-444A-AB1F-9BCD02DEA204}.Release|Any CPU.ActiveCfg = Release|Any CPU {02EE275F-6E2D-444A-AB1F-9BCD02DEA204}.Release|Any CPU.Build.0 = Release|Any CPU - {B8C004E3-F59E-4017-8781-C0F99B61BDEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B8C004E3-F59E-4017-8781-C0F99B61BDEF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B8C004E3-F59E-4017-8781-C0F99B61BDEF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B8C004E3-F59E-4017-8781-C0F99B61BDEF}.Release|Any CPU.Build.0 = Release|Any CPU - {12F96462-A2F8-4FBE-B4F5-29BA6A6DB4D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {12F96462-A2F8-4FBE-B4F5-29BA6A6DB4D9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {12F96462-A2F8-4FBE-B4F5-29BA6A6DB4D9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {12F96462-A2F8-4FBE-B4F5-29BA6A6DB4D9}.Release|Any CPU.Build.0 = Release|Any CPU {6981E761-E698-437D-AF63-0E80844B7D41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6981E761-E698-437D-AF63-0E80844B7D41}.Debug|Any CPU.Build.0 = Debug|Any CPU {6981E761-E698-437D-AF63-0E80844B7D41}.Release|Any CPU.ActiveCfg = Release|Any CPU {6981E761-E698-437D-AF63-0E80844B7D41}.Release|Any CPU.Build.0 = Release|Any CPU + {9EA4EA87-7656-48BA-BE7F-E5CC1B48512D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9EA4EA87-7656-48BA-BE7F-E5CC1B48512D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9EA4EA87-7656-48BA-BE7F-E5CC1B48512D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9EA4EA87-7656-48BA-BE7F-E5CC1B48512D}.Release|Any CPU.Build.0 = Release|Any CPU + {794C4984-BB46-4A50-9BC1-53831B5C8002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {794C4984-BB46-4A50-9BC1-53831B5C8002}.Debug|Any CPU.Build.0 = Debug|Any CPU + {794C4984-BB46-4A50-9BC1-53831B5C8002}.Release|Any CPU.ActiveCfg = Release|Any CPU + {794C4984-BB46-4A50-9BC1-53831B5C8002}.Release|Any CPU.Build.0 = Release|Any CPU + {F0A7B925-30F2-4FAA-97E6-7848B3E104B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0A7B925-30F2-4FAA-97E6-7848B3E104B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0A7B925-30F2-4FAA-97E6-7848B3E104B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0A7B925-30F2-4FAA-97E6-7848B3E104B6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NetFabric.Hyperlinq/Aggregation/Count/Count.ReadOnlyList.cs b/NetFabric.Hyperlinq/Aggregation/Count/Count.ReadOnlyList.cs deleted file mode 100644 index fd75b1be5..000000000 --- a/NetFabric.Hyperlinq/Aggregation/Count/Count.ReadOnlyList.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this TList source) - where TList : struct, IReadOnlyList - => source.Count(0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static int Count(this TList source, int offset, int count) - where TList : struct, IReadOnlyList - => count; - - static int Count(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - var counter = 0; - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - counter += predicate.Invoke(item).AsByte(); - } - return counter; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static int CountAt(this TList source, TPredicate predicate) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source.CountAt(predicate, 0, source.Count); - - static int CountAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate: struct, IFunction - { - var counter = 0; - var end = count; - if (offset is 0) - { - for (var index = 0; index < end; index++) - { - var item = source[index]; - counter += predicate.Invoke(source[index], index).AsByte(); - } - } - else - { - for (var index = 0; index < end; index++) - { - var item = source[index + offset]; - counter += predicate.Invoke(item, index).AsByte(); - } - } - return counter; - } - } -} - diff --git a/NetFabric.Hyperlinq/Aggregation/Count/Count.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Aggregation/Count/Count.ReadOnlySpan.cs deleted file mode 100644 index 73da3db62..000000000 --- a/NetFabric.Hyperlinq/Aggregation/Count/Count.ReadOnlySpan.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ReadOnlySpan source) - => source.Length; - - static int Count(this ReadOnlySpan source, TPredicate predicate) - where TPredicate: struct, IFunction - { - var counter = 0; - foreach (var item in source) - { - counter += predicate.Invoke(item).AsByte(); - } - return counter; - } - - static int CountRef(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunctionIn - { - var counter = 0; - foreach (ref readonly var item in source) - { - counter += predicate.Invoke(in item).AsByte(); - } - return counter; - } - - static int CountAt(this ReadOnlySpan source, TPredicate predicate) - where TPredicate: struct, IFunction - { - var counter = 0; - for (var index = 0; index < source.Length; index++) - { - var item = source[index]; - counter += predicate.Invoke(item, index).AsByte(); - } - return counter; - } - - static int CountAtRef(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunctionIn - { - var counter = 0; - for (var index = 0; index < source.Length; index++) - { - ref readonly var item = ref source[index]; - counter += predicate.Invoke(in item, index).AsByte(); - } - return counter; - } - } -} - diff --git a/NetFabric.Hyperlinq/Aggregation/Count/Count.Span.cs b/NetFabric.Hyperlinq/Aggregation/Count/Count.Span.cs deleted file mode 100644 index 9e860e5f1..000000000 --- a/NetFabric.Hyperlinq/Aggregation/Count/Count.Span.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this Span source) - => source.Length; - } -} - diff --git a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.ReadOnlyList.cs b/NetFabric.Hyperlinq/Aggregation/Sum/Sum.ReadOnlyList.cs deleted file mode 100644 index 09030dde1..000000000 --- a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.ReadOnlyList.cs +++ /dev/null @@ -1,188 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - public static TSum Sum(this TList source) - where TList : struct, IReadOnlyList - where TSum : struct - => source.Sum(0, source.Count); - - static TSum Sum(this TList source, int offset, int count) - where TList : struct, IReadOnlyList - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - static TSum Sum(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - static TSum SumRef(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(in item)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - static TSum SumAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - static TSum SumAtRef(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(in item, index)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - static TSum Sum(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - sum = GenericsOperator.AddNullable(selector.Invoke(item), sum); - } - return sum; - } - - static TSum SumRef(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - sum = GenericsOperator.AddNullable(selector.Invoke(in item), sum); - } - return sum; - } - - static TSum SumAt(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - sum = GenericsOperator.AddNullable(selector.Invoke(item, index), sum); - } - return sum; - } - - static TSum SumAtRef(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - sum = GenericsOperator.AddNullable(selector.Invoke(in item, index), sum); - } - return sum; - } - - - static TSum Sum(this TList source, TPredicate predicate, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item)) - sum = GenericsOperator.AddNullable(selector.Invoke(item), sum); - } - return sum; - } - - static TSum SumRef(this TList source, TPredicate predicate, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(in item)) - sum = GenericsOperator.AddNullable(selector.Invoke(in item), sum); - } - return sum; - } - } -} - diff --git a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Aggregation/Sum/Sum.ReadOnlySpan.cs deleted file mode 100644 index 04223d559..000000000 --- a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.ReadOnlySpan.cs +++ /dev/null @@ -1,257 +0,0 @@ -using System; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlySpan source) - => Sum(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlySpan source) - => Sum(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlySpan source) - => Sum(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlySpan source) - => Sum(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlySpan source) - => Sum(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlySpan source) - => Sum(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlySpan source) - => Sum(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlySpan source) - => Sum(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlySpan source) - => Sum(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlySpan source) - => Sum(source); - - /////////////////////////////////////////////////////////// - - static TSource Sum(this ReadOnlySpan source) - where TSource : struct - { - var sum = default(TSource); - - if (Vector.IsHardwareAccelerated && source.Length > Vector.Count * 2) // use SIMD - { - var vectors = MemoryMarshal.Cast>(source); - var vectorSum = Vector.Zero; - - foreach (var vector in vectors) - vectorSum += vector; - - for (var index = 0; index < Vector.Count; index++) - sum = GenericsOperator.Add(vectorSum[index], sum); - - for (var index = source.Length - (source.Length % Vector.Count); index < source.Length; index++) - { - var item = source[index]; - sum = GenericsOperator.Add(item, sum); - } - } - else - { - foreach (var item in source) - sum = GenericsOperator.Add(item, sum); - } - - return sum; - } - - static TResult Sum(this ReadOnlySpan source, TVectorSelector vectorSelector, TSelector selector) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - { - var sum = default(TResult); - - if (Vector.IsHardwareAccelerated && source.Length > Vector.Count * 2) // use SIMD - { - var vectors = MemoryMarshal.Cast>(source); - var vectorSum = Vector.Zero; - - foreach (var vector in vectors) - vectorSum += vectorSelector.Invoke(vector); - - for (var index = 0; index < Vector.Count; index++) - sum = GenericsOperator.Add(vectorSum[index], sum); - - for (var index = source.Length - (source.Length % Vector.Count); index < source.Length; index++) - { - var item = source[index]; - sum = GenericsOperator.Add(selector.Invoke(item), sum); - } - } - else - { - foreach (var item in source) - sum = GenericsOperator.Add(selector.Invoke(item), sum); - } - return sum; - } - - static TSum Sum(this ReadOnlySpan source) - where TSum : struct - { - var sum = default(TSum); - - foreach (var item in source) - sum = GenericsOperator.AddNullable(item, sum); - - return sum; - } - - static TSum Sum(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - foreach (var item in source) - { - if (predicate.Invoke(item)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - static TSum SumRef(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - foreach (ref readonly var item in source) - { - if (predicate.Invoke(in item)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - static TSum SumAt(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - for (var index = 0; index < source.Length; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - static TSum SumAtRef(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - for (var index = 0; index < source.Length; index++) - { - ref readonly var item = ref source[index]; - if (predicate.Invoke(in item, index)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - static TSum Sum(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - foreach (var item in source) - sum = GenericsOperator.AddNullable(selector.Invoke(item), sum); - return sum; - } - - static TSum SumRef(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - foreach (ref readonly var item in source) - sum = GenericsOperator.AddNullable(selector.Invoke(in item), sum); - return sum; - } - - static TSum SumAt(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - for (var index = 0; index < source.Length; index++) - { - var item = source[index]; - sum = GenericsOperator.AddNullable(selector.Invoke(item, index), sum); - } - return sum; - } - - static TSum SumAtRef(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - for (var index = 0; index < source.Length; index++) - { - ref readonly var item = ref source[index]; - sum = GenericsOperator.AddNullable(selector.Invoke(in item, index), sum); - } - return sum; - } - - - static TSum Sum(this ReadOnlySpan source, TPredicate predicate, TSelector selector) - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - foreach (var item in source) - { - if (predicate.Invoke(item)) - sum = GenericsOperator.AddNullable(selector.Invoke(item), sum); - } - return sum; - } - - static TSum SumRef(this ReadOnlySpan source, TPredicate predicate, TSelector selector) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - foreach (ref readonly var item in source) - { - if (predicate.Invoke(in item)) - sum = GenericsOperator.AddNullable(selector.Invoke(in item), sum); - } - return sum; - } - } -} - diff --git a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.Span.cs b/NetFabric.Hyperlinq/Aggregation/Sum/Sum.Span.cs deleted file mode 100644 index 687a80d70..000000000 --- a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.Span.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this Span source) - => ((ReadOnlySpan)source).Sum(); - } -} - diff --git a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.ValueEnumerable.cs b/NetFabric.Hyperlinq/Aggregation/Sum/Sum.ValueEnumerable.cs deleted file mode 100644 index 9c14936ba..000000000 --- a/NetFabric.Hyperlinq/Aggregation/Sum/Sum.ValueEnumerable.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - internal static TSum Sum(this TEnumerable source) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - sum = GenericsOperator.AddNullable(enumerator.Current, sum); - return sum; - } - - internal static TSum Sum(this TEnumerable source, TPredicate predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - { - var item = enumerator.Current; - if (predicate.Invoke(item)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - internal static TSum SumRef(this TEnumerable source, TPredicate predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - { - var item = enumerator.Current; - if (predicate.Invoke(in item)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - internal static TSum SumAt(this TEnumerable source, TPredicate predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - for (var index = 0; enumerator.MoveNext(); index++) - { - var item = enumerator.Current; - if (predicate.Invoke(item, index)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - internal static TSum SumAtRef(this TEnumerable source, TPredicate predicate) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - for (var index = 0; enumerator.MoveNext(); index++) - { - var item = enumerator.Current; - if (predicate.Invoke(in item, index)) - sum = GenericsOperator.AddNullable(item, sum); - } - return sum; - } - - internal static TSum Sum(this TEnumerable source, TSelector selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - { - var item = enumerator.Current; - sum = GenericsOperator.AddNullable(selector.Invoke(item), sum); - } - return sum; - } - - internal static TSum SumRef(this TEnumerable source, TSelector selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - { - var item = enumerator.Current; - sum = GenericsOperator.AddNullable(selector.Invoke(in item), sum); - } - return sum; - } - - static TSum SumAt(this TEnumerable source, TSelector selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - for (var index = 0; enumerator.MoveNext(); index++) - { - var item = enumerator.Current; - sum = GenericsOperator.AddNullable(selector.Invoke(item, index), sum); - } - return sum; - } - - internal static TSum SumAtRef(this TEnumerable source, TSelector selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - for (var index = 0; enumerator.MoveNext(); index++) - { - var item = enumerator.Current; - sum = GenericsOperator.AddNullable(selector.Invoke(in item, index), sum); - } - return sum; - } - - - internal static TSum Sum(this TEnumerable source, TPredicate predicate, TSelector selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - { - var item = enumerator.Current; - if (predicate.Invoke(item)) - sum = GenericsOperator.AddNullable(selector.Invoke(item), sum); - } - return sum; - } - - internal static TSum SumRef(this TEnumerable source, TPredicate predicate, TSelector selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - where TSum : struct - { - var sum = default(TSum); - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - { - var item = enumerator.Current; - if (predicate.Invoke(in item)) - sum = GenericsOperator.AddNullable(selector.Invoke(in item), sum); - } - return sum; - } - } -} - diff --git a/NetFabric.Hyperlinq/Attributes/GeneratorBindingsAttribute.cs b/NetFabric.Hyperlinq/Attributes/GeneratorBindingsAttribute.cs new file mode 100644 index 000000000..65a9076f5 --- /dev/null +++ b/NetFabric.Hyperlinq/Attributes/GeneratorBindingsAttribute.cs @@ -0,0 +1,31 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +namespace NetFabric.Hyperlinq +{ + [ExcludeFromCodeCoverage] + [AttributeUsage(AttributeTargets.Struct)] + public sealed class GeneratorBindingsAttribute + : Attribute + { + public string Source { get; } + public string ElementType { get; } + public string? SourceImplements { get; } + public string? EnumerableType { get; } + public string? EnumeratorType { get; } + public string? ExtraTypeParameters { get; } + public string? ExtraParameters { get; } + + public GeneratorBindingsAttribute( + string source = "this", + string elementType = "TSource", + string? sourceImplements = default, + string? enumerableType = default, + string? enumeratorType = default, + string? extraTypeParameters = default, + string? extraParameters = default + ) + => (Source, ElementType, SourceImplements, EnumerableType, EnumeratorType, ExtraTypeParameters, ExtraParameters) + = (source, elementType, sourceImplements, enumerableType, enumeratorType, extraTypeParameters, extraParameters); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/GeneratorIgnoreAttribute.cs b/NetFabric.Hyperlinq/Attributes/GeneratorIgnoreAttribute.cs similarity index 83% rename from NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/GeneratorIgnoreAttribute.cs rename to NetFabric.Hyperlinq/Attributes/GeneratorIgnoreAttribute.cs index d7e78203d..5a6e3ac40 100644 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Source/Common/GeneratorIgnoreAttribute.cs +++ b/NetFabric.Hyperlinq/Attributes/GeneratorIgnoreAttribute.cs @@ -5,7 +5,8 @@ namespace NetFabric.Hyperlinq { [ExcludeFromCodeCoverage] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method)] - public sealed class GeneratorIgnoreAttribute : Attribute + public sealed class GeneratorIgnoreAttribute + : Attribute { public bool Value { get; } diff --git a/NetFabric.Hyperlinq/Utils/Generator/GeneratorMappingAttribute.cs b/NetFabric.Hyperlinq/Attributes/GeneratorMappingAttribute.cs similarity index 87% rename from NetFabric.Hyperlinq/Utils/Generator/GeneratorMappingAttribute.cs rename to NetFabric.Hyperlinq/Attributes/GeneratorMappingAttribute.cs index e17af8931..5c76a2336 100644 --- a/NetFabric.Hyperlinq/Utils/Generator/GeneratorMappingAttribute.cs +++ b/NetFabric.Hyperlinq/Attributes/GeneratorMappingAttribute.cs @@ -5,7 +5,8 @@ namespace NetFabric.Hyperlinq { [ExcludeFromCodeCoverage] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method, AllowMultiple = true)] - public sealed class GeneratorMappingAttribute : Attribute + public sealed class GeneratorMappingAttribute + : Attribute { public string From { get; } public string To { get; } diff --git a/NetFabric.Hyperlinq/CompilationContext.cs b/NetFabric.Hyperlinq/CompilationContext.cs new file mode 100644 index 000000000..a2a169618 --- /dev/null +++ b/NetFabric.Hyperlinq/CompilationContext.cs @@ -0,0 +1,32 @@ +using Microsoft.CodeAnalysis; +using NetFabric.CodeAnalysis; +using System; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + sealed class CompilationContext + { + public Compilation Compilation { get; } + public string GeneratedCodeAttribute { get; } + public INamedTypeSymbol GeneratorIgnoreAttribute { get; } + public INamedTypeSymbol GeneratorBindingsAttribute { get; } + public INamedTypeSymbol GeneratorMappingAttribute { get; } + + public CompilationContext(Compilation compilation) + { + Compilation = compilation; + + var generatorAssembly = GetType().Assembly; + var generatorAssemblyName = generatorAssembly.GetName().Name; + var generatorAssemblyVersion = AttributeExtensions.GetCustomAttribute(generatorAssembly)?.InformationalVersion ?? string.Empty; + GeneratedCodeAttribute = $"[GeneratedCode(\"{generatorAssemblyName}\", \"{generatorAssemblyVersion}\")]"; + + GeneratorIgnoreAttribute = compilation.GetTypeByMetadataName(typeof(GeneratorIgnoreAttribute).FullName) + ?? throw new Exception("GeneratorIgnoreAttribute symbol not found!"); + GeneratorBindingsAttribute = compilation.GetTypeByMetadataName(typeof(GeneratorBindingsAttribute).FullName) + ?? throw new Exception("GeneratorBindingsAttribute symbol not found!"); + GeneratorMappingAttribute = compilation.GetTypeByMetadataName(typeof(GeneratorMappingAttribute).FullName) + ?? throw new Exception("GeneratorMappingAttribute symbol not found!"); + } + } +} diff --git a/NetFabric.Hyperlinq/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncEnumerable.cs b/NetFabric.Hyperlinq/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncEnumerable.cs deleted file mode 100644 index 0cf1fc697..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncEnumerable.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; - -namespace NetFabric.Hyperlinq -{ - public static partial class AsyncEnumerableExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static AsyncValueEnumerableWrapper AsAsyncValueEnumerable(this IAsyncEnumerable source) - => new(source); - - [GeneratorIgnore] // TODO: to be removed - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static AsyncValueEnumerableWrapper AsAsyncValueEnumerable(this TEnumerable source, Func getAsyncEnumerator) - where TEnumerable : IAsyncEnumerable - where TEnumerator : struct, IAsyncEnumerator - => new(source, getAsyncEnumerator); - - public readonly partial struct AsyncValueEnumerableWrapper - : IAsyncValueEnumerable - where TEnumerable : IAsyncEnumerable - where TEnumerator : struct, IAsyncEnumerator - { - readonly TEnumerable source; - readonly Func getAsyncEnumerator; - - internal AsyncValueEnumerableWrapper(TEnumerable source, Func getAsyncEnumerator) - { - this.source = source; - this.getAsyncEnumerator = getAsyncEnumerator; - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly TEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - => getAsyncEnumerator(source, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) - // ReSharper disable once HeapView.BoxingAllocation - => getAsyncEnumerator(source, cancellationToken); - } - - public readonly partial struct AsyncValueEnumerableWrapper - : IAsyncValueEnumerable.AsyncEnumerator> - { - readonly IAsyncEnumerable source; - - internal AsyncValueEnumerableWrapper(IAsyncEnumerable source) - => this.source = source; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly AsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - => new(source, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) - // ReSharper disable once HeapView.BoxingAllocation - => new AsyncEnumerator(source, cancellationToken); - - public readonly partial struct AsyncEnumerator - : IAsyncEnumerator - { - readonly IAsyncEnumerator enumerator; - - internal AsyncEnumerator(IAsyncEnumerable enumerable, CancellationToken cancellationToken) - => enumerator = enumerable.GetAsyncEnumerator(cancellationToken); - - public readonly TSource Current - => enumerator.Current; - readonly TSource IAsyncEnumerator.Current - => enumerator.Current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueTask MoveNextAsync() - => enumerator.MoveNextAsync(); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueTask DisposeAsync() - => enumerator.DisposeAsync(); - } - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncValueEnumerable.cs deleted file mode 100644 index b1adc1b5b..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.AsyncValueEnumerable.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class AsyncValueEnumerableExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TEnumerable AsAsyncValueEnumerable(this TEnumerable source) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - => source; - } -} diff --git a/NetFabric.Hyperlinq/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.ValueEnumerable.cs b/NetFabric.Hyperlinq/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.ValueEnumerable.cs deleted file mode 100644 index d6c0d244e..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsAsyncValueEnumerable/AsAsyncValueEnumerable.ValueEnumerable.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static AsyncValueEnumerableWrapper AsAsyncValueEnumerable(this TEnumerable source) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => new(source); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct AsyncValueEnumerableWrapper - : IAsyncValueEnumerable.AsyncEnumerator> - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - { - readonly TEnumerable source; - - internal AsyncValueEnumerableWrapper(TEnumerable source) - => this.source = source; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly AsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - cancellationToken.ThrowIfCancellationRequested(); - return new AsyncEnumerator(source, cancellationToken); - } - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) - // ReSharper disable once HeapView.BoxingAllocation - => GetAsyncEnumerator(cancellationToken); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct AsyncEnumerator - : IAsyncEnumerator - { - readonly TEnumerator enumerator; - readonly CancellationToken cancellationToken; - - internal AsyncEnumerator(TEnumerable enumerable, CancellationToken cancellationToken) - { - enumerator = enumerable.GetEnumerator(); - this.cancellationToken = cancellationToken; - } - - public readonly TSource Current - => enumerator.Current; - readonly TSource IAsyncEnumerator.Current - => enumerator.Current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask MoveNextAsync() - { - cancellationToken.ThrowIfCancellationRequested(); - return new ValueTask(enumerator.MoveNext()); - } - - public ValueTask DisposeAsync() - { - enumerator.Dispose(); - return default; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask ToArrayAsync(CancellationToken cancellationToken = default) - => new(result: source.ToArray()); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueTask> ToListAsync(CancellationToken cancellationToken = default) - => new(result: source.ToList()); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.cs deleted file mode 100644 index 1ad4541c1..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class EnumerableExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable AsValueEnumerable(this IEnumerable source) - => new(source); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct ValueEnumerable - : IValueEnumerable> - { - readonly IEnumerable source; - - internal ValueEnumerable(IEnumerable source) - => this.source = source; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerator GetEnumerator() - => new(source.GetEnumerator()); - IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => GetEnumerator(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, int, int>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, int?, int>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, long, long>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, long?, long>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, float, float>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, float?, float>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, double, double>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, double?, double>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, decimal, decimal>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerable source) - => source.Sum, ValueEnumerator, decimal?, decimal>(); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.cs deleted file mode 100644 index 96de369c3..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyCollectionExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable AsValueEnumerable(this IReadOnlyCollection source) - => new(source); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct ValueEnumerable - : IValueReadOnlyCollection> - , ICollection - { - readonly IReadOnlyCollection source; - - internal ValueEnumerable(IReadOnlyCollection source) - => this.source = source; - - public int Count - => source.Count; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerator GetEnumerator() - => new(source.GetEnumerator()); - IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => GetEnumerator(); - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(Span span) - { - if (span.Length < Count) - Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - - if (source.Count is not 0) - { - using var enumerator = GetEnumerator(); - checked - { - for (var index = 0; enumerator.MoveNext(); index++) - span[index] = enumerator.Current; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TSource[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource item) - => Count is not 0 && EnumerableExtensions.Contains(source, item); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TSource item) - => Throw.NotSupportedException(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource value, IEqualityComparer? comparer) - => Count is not 0 && source.Contains(value, comparer); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ValueEnumerable source) - => source.Count; - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.cs deleted file mode 100644 index 4cb5227ee..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class EnumerableExtensions - { - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable, FunctionWrapper> AsValueEnumerable(this TEnumerable source, Func getEnumerator) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - => AsValueEnumerable>(source, new FunctionWrapper(getEnumerator)); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable AsValueEnumerable(this TEnumerable source, TGetEnumerator getEnumerator = default) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TGetEnumerator : struct, IFunction - => new(source, getEnumerator, getEnumerator); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable, FunctionWrapper> AsValueEnumerable(this TEnumerable source, Func getEnumerator, Func getEnumerator2) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - => AsValueEnumerable, FunctionWrapper>(source, new FunctionWrapper(getEnumerator), new FunctionWrapper(getEnumerator2)); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable AsValueEnumerable(this TEnumerable source, TGetEnumerator getEnumerator = default, TGetEnumerator2 getEnumerator2 = default) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => new(source, getEnumerator, getEnumerator2); - - [StructLayout(LayoutKind.Auto)] - public partial struct ValueEnumerable - : IValueEnumerable - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - { - readonly TEnumerable source; - TGetEnumerator getEnumerator; - TGetEnumerator2 getEnumerator2; - - internal ValueEnumerable(TEnumerable source, TGetEnumerator getEnumerator, TGetEnumerator2 getEnumerator2) - => (this.source, this.getEnumerator, this.getEnumerator2) = (source, getEnumerator, getEnumerator2); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TEnumerator2 GetEnumerator() - => getEnumerator2.Invoke(source); - TEnumerator IValueEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => getEnumerator.Invoke(source); - IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => getEnumerator.Invoke(source); - IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => getEnumerator.Invoke(source); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, int, int>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, int?, int>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, long, long>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, long?, long>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, float, float>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, float?, float>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, double, double>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, double?, double>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, decimal, decimal>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerable source) - where TEnumerable : IEnumerable - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, decimal?, decimal>(); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.cs deleted file mode 100644 index 71d5d6d22..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.cs +++ /dev/null @@ -1,218 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyCollectionExtensions - { - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable, FunctionWrapper> AsValueEnumerable(this TEnumerable source, Func getEnumerator) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - => AsValueEnumerable>(source, new FunctionWrapper(getEnumerator)); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable AsValueEnumerable(this TEnumerable source, TGetEnumerator getEnumerator = default) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TGetEnumerator : struct, IFunction - => new(source, getEnumerator, getEnumerator); - - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable, FunctionWrapper> AsValueEnumerable(this TEnumerable source, Func getEnumerator, Func getEnumerator2) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - => AsValueEnumerable, FunctionWrapper>(source, new FunctionWrapper(getEnumerator), new FunctionWrapper(getEnumerator2)); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable AsValueEnumerable(this TEnumerable source, TGetEnumerator getEnumerator = default, TGetEnumerator2 getEnumerator2 = default) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => new(source, getEnumerator, getEnumerator2); - - [StructLayout(LayoutKind.Auto)] - public partial struct ValueEnumerable - : IValueReadOnlyCollection - , ICollection - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - { - readonly TEnumerable source; - TGetEnumerator getEnumerator; - TGetEnumerator2 getEnumerator2; - - internal ValueEnumerable(TEnumerable source, TGetEnumerator getEnumerator, TGetEnumerator2 getEnumerator2) - => (this.source, this.getEnumerator, this.getEnumerator2) = (source, getEnumerator, getEnumerator2); - - public readonly int Count - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TEnumerator2 GetEnumerator() - => getEnumerator2.Invoke(source); - TEnumerator IValueEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => getEnumerator.Invoke(source); - IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => getEnumerator.Invoke(source); - IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => getEnumerator.Invoke(source); - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(Span span) - { - if (span.Length < Count) - Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - - if (source.Count is not 0) - { - using var enumerator = getEnumerator.Invoke(source); - checked - { - for (var index = 0; enumerator.MoveNext(); index++) - span[index] = enumerator.Current; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TSource[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource item) - => Count is not 0 && EnumerableExtensions.Contains(source, item); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TSource item) - => Throw.NotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, int, int>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, int?, int>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, long, long>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, long?, long>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, float, float>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, float?, float>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, double, double>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, double?, double>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, decimal, decimal>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerable source) - where TEnumerable : IReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TEnumerator2 : struct - where TGetEnumerator : struct, IFunction - where TGetEnumerator2 : struct, IFunction - => source.Sum, TEnumerator, decimal?, decimal>(); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs deleted file mode 100644 index ad1dbca31..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs +++ /dev/null @@ -1,405 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ArraySegmentValueEnumerable AsValueEnumerable(this ArraySegment source) - => new(source); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct ArraySegmentValueEnumerable - : IValueReadOnlyList.DisposableEnumerator> - , IList - { - internal readonly ArraySegment source; - - internal ArraySegmentValueEnumerable(ArraySegment source) - => this.source = source; - - public readonly int Count - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source.Count; - } - - public readonly TSource this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((uint)index >= (uint)source.Count) Throw.IndexOutOfRangeException(); - - return source.Array![source.Offset + index]; - } - } - TSource IReadOnlyList.this[int index] - => this[index]; - TSource IList.this[int index] - { - get => this[index]; - - [ExcludeFromCodeCoverage] - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SpanEnumerator GetEnumerator() - => new(source); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(source); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(source); - - - bool ICollection.IsReadOnly - => true; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(Span span) - => source.AsSpan().CopyTo(span); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TSource[] array, int arrayIndex) - => Copy(source, array.AsSpan().Slice(arrayIndex)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource item) - => ((ICollection)source).Contains(item); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int IndexOf(TSource item) - => ArrayExtensions.IndexOf(source.AsSpan(), item); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - - [ExcludeFromCodeCoverage] - void IList.Insert(int index, TSource item) - => Throw.NotSupportedException(); - - [ExcludeFromCodeCoverage] - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly ArraySegment source; - int index; - - internal DisposableEnumerator(ArraySegment source) - { - this.source = source; - index = -1; - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source.Array![source.Offset + index]; - } - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => this.Current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index < source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ExcludeFromCodeCoverage] - public void Reset() - => index = -1; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void Dispose() { } - } - - #region Aggregation - - #endregion - - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentValueEnumerable AsEnumerable() - => this; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentValueEnumerable AsValueEnumerable() - => this; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TSource[] ToArray() - => source.AsSpan().ToArray(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.AsSpan().ToArray(memoryPool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.AsSpan().ToList(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.AsSpan().ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => source.AsSpan().ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.AsSpan().ToDictionary(keySelector, elementSelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => source.AsSpan().ToDictionary(keySelector, elementSelector, comparer); - - #endregion - - #region Element - - public Option ElementAt(int index) - => source.AsSpan().ElementAt(index); - - public Option First() - => source.AsSpan().First(); - - public Option Single() - => source.AsSpan().Single(); - - #endregion - - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereEnumerable> Where(Func predicate) - => source.Where(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereEnumerable Where(TPredicate predicate = default) - where TPredicate : struct, IFunction - => source.Where(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereAtEnumerable> Where(Func predicate) - => source.Where(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereAtEnumerable WhereAt(TPredicate predicate = default) - where TPredicate : struct, IFunction - => source.WhereAt(predicate); - - #endregion - - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentValueEnumerable Skip(int count) - { - var (skipCount, takeCount) = Utils.Skip(source.Count, count); - return new ArraySegmentValueEnumerable(new ArraySegment(source.Array!, source.Offset + skipCount, takeCount)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentValueEnumerable Take(int count) - => new(new ArraySegment(source.Array!, source.Offset, Utils.Take(source.Count, count))); - - #endregion - - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentSelectEnumerable> Select(Func selector) - => source.Select(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentSelectEnumerable Select(TSelector selector = default) - where TSelector : struct, IFunction - => source.Select(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentSelectAtEnumerable> Select(Func selector) - => source.Select(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentSelectAtEnumerable SelectAt(TSelector selector = default) - where TSelector : struct, IFunction - => source.SelectAt(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentSelectManyEnumerable> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => source.SelectMany(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentSelectManyEnumerable SelectMany(TSelector selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => source.SelectMany(selector); - - #endregion - - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate predicate) - where TPredicate : struct, IFunction - => source.AsSpan().All(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate predicate) - where TPredicate : struct, IFunction - => source.AsSpan().AllAt(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.AsSpan().Any(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate predicate) - where TPredicate : struct, IFunction - => source.AsSpan().Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate predicate) - where TPredicate : struct, IFunction - => source.AsSpan().AnyAt(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource value, IEqualityComparer? comparer) - => source.AsSpan().Contains(value, comparer); - - #endregion - - #region Set - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentDistinctEnumerable Distinct(IEqualityComparer? comparer = default) - => source.Distinct(comparer); - - #endregion - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ArraySegmentValueEnumerable source) - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentValueEnumerable source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool ContainsVector(this ArraySegmentValueEnumerable source, TSource value) - where TSource : struct - => source.source.AsSpan().ContainsVector(value); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static MemorySelectVectorContext, Vector>, FunctionWrapper> SelectVector(this ArraySegmentValueEnumerable source, Func, Vector> vectorSelector, Func selector) - where TSource : struct - where TResult : struct - => source.source.SelectVector(vectorSelector, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static MemorySelectVectorContext SelectVector(this ArraySegmentValueEnumerable source, TSelector selector = default) - where TSelector : struct, IFunction, Vector>, IFunction - where TSource : struct - where TResult : struct - => source.source.SelectVector(selector, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static MemorySelectVectorContext SelectVector(this ArraySegmentValueEnumerable source, TVectorSelector vectorSelector = default, TSelector selector = default) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - => source.source.SelectVector(vectorSelector, selector); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.cs deleted file mode 100644 index f2399f52a..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.cs +++ /dev/null @@ -1,413 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ListValueEnumerable AsValueEnumerable(this IReadOnlyList source) - => new(source, 0, source.Count); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct ListValueEnumerable - : IValueReadOnlyList.DisposableEnumerator> - , IList - { - internal readonly IReadOnlyList source; - internal readonly int offset; - - internal ListValueEnumerable(IReadOnlyList source, int offset, int count) - => (this.source, this.offset, Count) = (source, offset, count); - - public readonly int Count { get; } - - public readonly TSource this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if (index < 0 || index >= Count) Throw.IndexOutOfRangeException(); - - return source[index + offset]; - } - } - TSource IReadOnlyList.this[int index] - => this[index]; - TSource IList.this[int index] - { - get => this[index]; - - [ExcludeFromCodeCoverage] - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(Span span) - { - if (span.Length < Count) - Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - - Copy(this, 0, span, Count); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TSource[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource item) - { - var end = offset + Count; - for (var index = offset; index < end; index++) - { - if (EqualityComparer.Default.Equals(source[index], item)) - return true; - } - return false; - } - - public int IndexOf(TSource item) - => ReadOnlyListExtensions.IndexOf(source, item, offset, Count); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - - [ExcludeFromCodeCoverage] - void IList.Insert(int index, TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - { - readonly IReadOnlyList source; - readonly int end; - int index; - - internal Enumerator(in ListValueEnumerable enumerable) - { - source = enumerable.source; - index = enumerable.offset - 1; - end = index + enumerable.Count; - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index <= end; - } - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly IReadOnlyList source; - readonly int end; - int index; - - internal DisposableEnumerator(in ListValueEnumerable enumerable) - { - source = enumerable.source; - index = enumerable.offset - 1; - end = index + enumerable.Count; - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source[index]; - } - readonly TSource IEnumerator.Current - => source[index]; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => source[index]; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index <= end; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ExcludeFromCodeCoverage] - public void Reset() - => Throw.NotSupportedException(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void Dispose() { } - } - - #region Aggregation - - #endregion - - #region Conversion - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ListValueEnumerable AsEnumerable() - // => this; - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ListValueEnumerable AsValueEnumerable() - // => this; - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public TSource[] ToArray() - // => ReadOnlyListExtensions.ToArray(source, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public IMemoryOwner ToArray(MemoryPool memoryPool) - // => ReadOnlyListExtensions.ToArray(source, offset, Count, memoryPool); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public List ToList() - // => ReadOnlyListExtensions.ToList(source, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - // where TKey : notnull - // => ReadOnlyListExtensions.ToDictionary(source, keySelector, comparer, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - // where TKey : notnull - // where TKeySelector : struct, IFunction - // => ReadOnlyListExtensions.ToDictionary(source, keySelector, comparer, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - // where TKey : notnull - // => ReadOnlyListExtensions.ToDictionary(source, keySelector, elementSelector, comparer, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - // where TKey : notnull - // where TKeySelector : struct, IFunction - // where TElementSelector : struct, IFunction - // => ReadOnlyListExtensions.ToDictionary(source, keySelector, elementSelector, comparer, offset, Count); - - #endregion - - #region Element - - // public Option ElementAt(int index) - // => ReadOnlyListExtensions.ElementAt(source, index, offset, Count); - // - // public Option First() - // => ReadOnlyListExtensions.First(source, offset, Count); - // - // public Option Single() - // => ReadOnlyListExtensions.Single(source, offset, Count); - - #endregion - - #region Filtering - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public WhereEnumerable> Where(Func predicate) - // => ReadOnlyListExtensions.Where(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public WhereEnumerable Where(TPredicate predicate = default) - // where TPredicate : struct, IFunction - // => ReadOnlyListExtensions.Where(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public WhereAtEnumerable> Where(Func predicate) - // => ReadOnlyListExtensions.Where(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public WhereAtEnumerable WhereAt(TPredicate predicate = default) - // where TPredicate : struct, IFunction - // => ReadOnlyListExtensions.WhereAt(source, predicate, offset, Count); - - #endregion - - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ListValueEnumerable Skip(int count) - { - var (skipCount, takeCount) = Utils.Skip(Count, count); - return new ListValueEnumerable(source, offset + skipCount, takeCount); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ListValueEnumerable Take(int count) - => new(source, offset, Utils.Take(Count, count)); - - #endregion - - #region Projection - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public SelectEnumerable> Select(Func selector) - // => ReadOnlyListExtensions.Select(source, selector, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public SelectEnumerable Select(TSelector selector = default) - // where TSelector : struct, IFunction - // => ReadOnlyListExtensions.Select(source, selector, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public SelectAtEnumerable> Select(Func selector) - // => ReadOnlyListExtensions.Select(source, selector, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public SelectAtEnumerable SelectAt(TSelector selector = default) - // where TSelector : struct, IFunction - // => ReadOnlyListExtensions.SelectAt(source, selector, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public SelectManyEnumerable> SelectMany(Func selector) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // => ReadOnlyListExtensions.SelectMany(source, selector, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public SelectManyEnumerable SelectMany(TSelector selector = default) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // where TSelector : struct, IFunction - // => ReadOnlyListExtensions.SelectMany(source, selector, offset, Count); - - #endregion - - #region Quantifier - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool All(Func predicate) - // => ReadOnlyListExtensions.All(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool All(TPredicate predicate) - // where TPredicate : struct, IFunction - // => ReadOnlyListExtensions.All(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool All(Func predicate) - // => ReadOnlyListExtensions.All(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool AllAt(TPredicate predicate) - // where TPredicate : struct, IFunction - // => ReadOnlyListExtensions.AllAt(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool Any() - // => ReadOnlyListExtensions.Any(source, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool Any(Func predicate) - // => ReadOnlyListExtensions.Any(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool Any(TPredicate predicate) - // where TPredicate : struct, IFunction - // => ReadOnlyListExtensions.Any(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool Any(Func predicate) - // => ReadOnlyListExtensions.Any(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool AnyAt(TPredicate predicate) - // where TPredicate : struct, IFunction - // => ReadOnlyListExtensions.AnyAt(source, predicate, offset, Count); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool Contains(TSource value, IEqualityComparer? comparer) - // => ReadOnlyListExtensions.Contains(source, value, comparer, offset, Count); - - #endregion - - #region Set - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public DistinctEnumerable Distinct(IEqualityComparer? comparer = default) - // => ReadOnlyListExtensions.Distinct(source, comparer, offset, Count); - - #endregion - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this in ListValueEnumerable source) - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ListValueEnumerable source) - => source.Sum, int, int>(source.offset, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ListValueEnumerable source) - => source.Sum, int?, int>(source.offset, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ListValueEnumerable source) - => source.Sum, long, long>(source.offset, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ListValueEnumerable source) - => source.Sum, long?, long>(source.offset, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ListValueEnumerable source) - => source.Sum, float, int>(source.offset, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ListValueEnumerable source) - => source.Sum, float?, float>(source.offset, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ListValueEnumerable source) - => source.Sum, double, double>(source.offset, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ListValueEnumerable source) - => source.Sum, double?, double>(source.offset, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ListValueEnumerable source) - => source.Sum, decimal, decimal>(source.offset, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ListValueEnumerable source) - => source.Sum, decimal?, decimal>(source.offset, source.Count); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ValueEnumerable.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ValueEnumerable.cs deleted file mode 100644 index af42a4c86..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ValueEnumerable.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TEnumerable AsValueEnumerable(this TEnumerable source) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source; - } -} diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.cs deleted file mode 100644 index 042036bec..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static class ListBindings - { - // List is simply converted to ArraySegment and share its IValueEnumerable wrapper. - // It's not converted to ReadOnlySpan because its enumerators cannot be casted to IEnumerable, restricting its use. - // It's not converted to ReadOnlyMemory because it's less efficient in enumerables (it has to call .Span on each iteration). - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ArrayExtensions.ArraySegmentValueEnumerable AsValueEnumerable(this List source) - => source.AsArraySegment().AsValueEnumerable(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ArrayExtensions.ArraySegmentValueEnumerableRef AsValueEnumerableRef(this List source) - => source.AsArraySegment().AsValueEnumerableRef(); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.cs deleted file mode 100644 index c9f85c2c7..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static class ImmutableArrayExtensions - { - // ImmutableArray implements IReadOnlyList - // No need for bindings -/* - // ImmutableArray implements IReadOnlyCollection and has two enumerators: - // One that is a value-type and doesn't implement interfaces. - // Another that is a reference-type and implements IEnumerator. - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlyCollectionExtensions.ValueEnumerable, ValueEnumerator, ImmutableArray.Enumerator, TSource, GetEnumerator, GetEnumerator2> AsValueEnumerable(this ImmutableArray source) - => ReadOnlyCollectionExtensions.AsValueEnumerable, ValueEnumerator, ImmutableArray.Enumerator, TSource, GetEnumerator, GetEnumerator2>(source); - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator - : IFunction, ValueEnumerator> - { - public ValueEnumerator Invoke(ImmutableArray source) - => new(((IEnumerable)source).GetEnumerator()); - } - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator2 - : IFunction, ImmutableArray.Enumerator> - { - public ImmutableArray.Enumerator Invoke(ImmutableArray source) - => source.GetEnumerator(); - } -*/ - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableDictionary.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableDictionary.cs deleted file mode 100644 index f8a02593d..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableDictionary.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static class ImmutableDictionaryExtensions - { - // ImmutableDictionary implements IReadOnlyCollection> and has a value-type enumerator that implements IEnumerator - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlyCollectionExtensions.ValueEnumerable, ImmutableDictionary.Enumerator, ImmutableDictionary.Enumerator, KeyValuePair, GetEnumerator, GetEnumerator> AsValueEnumerable(this ImmutableDictionary source) - where TKey: notnull - => ReadOnlyCollectionExtensions.AsValueEnumerable, ImmutableDictionary.Enumerator, KeyValuePair, GetEnumerator>(source); - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator - : IFunction, ImmutableDictionary.Enumerator> - where TKey: notnull - { - public ImmutableDictionary.Enumerator Invoke(ImmutableDictionary source) - => source.GetEnumerator(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableHashSet.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableHashSet.cs deleted file mode 100644 index fe24f214f..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableHashSet.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Immutable; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static class ImmutableHashSetExtensions - { - // ImmutableHashSet implements IReadOnlyCollection and has a value-type enumerator that implements IEnumerator - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlyCollectionExtensions.ValueEnumerable, ImmutableHashSet.Enumerator, ImmutableHashSet.Enumerator, TSource, GetEnumerator, GetEnumerator> AsValueEnumerable(this ImmutableHashSet source) - => ReadOnlyCollectionExtensions.AsValueEnumerable, ImmutableHashSet.Enumerator, TSource, GetEnumerator>(source); - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator - : IFunction, ImmutableHashSet.Enumerator> - { - public ImmutableHashSet.Enumerator Invoke(ImmutableHashSet source) - => source.GetEnumerator(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableList.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableList.cs deleted file mode 100644 index 186dad50d..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableList.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Immutable; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static class ImmutableListExtensions - { - // ImmutableList implements IReadOnlyCollection and has a value-type enumerator that implements IEnumerator - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlyCollectionExtensions.ValueEnumerable, ImmutableList.Enumerator, ImmutableList.Enumerator, TSource, GetEnumerator, GetEnumerator> AsValueEnumerable(this ImmutableList source) - => ReadOnlyCollectionExtensions.AsValueEnumerable, ImmutableList.Enumerator, TSource, GetEnumerator>(source); - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator - : IFunction, ImmutableList.Enumerator> - { - public ImmutableList.Enumerator Invoke(ImmutableList source) - => source.GetEnumerator(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableQueue.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableQueue.cs deleted file mode 100644 index d17458b2a..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableQueue.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static class ImmutableQueueExtensions - { - // ImmutableQueue implements IEnumerable and has two enumerators: - // One that is a value-type and doesn't implement interfaces. - // Another that is a reference-type and implements IEnumerator. - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EnumerableExtensions.ValueEnumerable, ValueEnumerator, ImmutableQueue.Enumerator, TSource, GetEnumerator, GetEnumerator2> AsValueEnumerable(this ImmutableQueue source) - => source.AsValueEnumerable, ValueEnumerator, ImmutableQueue.Enumerator, TSource, GetEnumerator, GetEnumerator2>(); - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator - : IFunction, ValueEnumerator> - { - public ValueEnumerator Invoke(ImmutableQueue source) - => new(((IEnumerable)source).GetEnumerator()); - } - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator2 - : IFunction, ImmutableQueue.Enumerator> - { - public ImmutableQueue.Enumerator Invoke(ImmutableQueue source) - => source.GetEnumerator(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableSortedDictionary.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableSortedDictionary.cs deleted file mode 100644 index dbbeacda5..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableSortedDictionary.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static class ImmutableSortedDictionaryExtensions - { - // ImmutableSortedDictionary implements IReadOnlyCollection> and has a value-type enumerator that implements IEnumerator - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlyCollectionExtensions.ValueEnumerable, ImmutableSortedDictionary.Enumerator, ImmutableSortedDictionary.Enumerator, KeyValuePair, GetEnumerator, GetEnumerator> AsValueEnumerable(this ImmutableSortedDictionary source) - where TKey: notnull - => ReadOnlyCollectionExtensions.AsValueEnumerable, ImmutableSortedDictionary.Enumerator, KeyValuePair, GetEnumerator>(source); - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator - : IFunction, ImmutableSortedDictionary.Enumerator> - where TKey: notnull - { - public ImmutableSortedDictionary.Enumerator Invoke(ImmutableSortedDictionary source) - => source.GetEnumerator(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableStack.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableStack.cs deleted file mode 100644 index 77242d89a..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableStack.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static class ImmutableStackExtensions - { - // ImmutableStack implements IEnumerable and has two enumerators: - // One that is a value-type and doesn't implement interfaces. - // Another that is a reference-type and implements IEnumerator. - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EnumerableExtensions.ValueEnumerable, ValueEnumerator, ImmutableStack.Enumerator, TSource, GetEnumerator, GetEnumerator2> AsValueEnumerable(this ImmutableStack source) - => source.AsValueEnumerable, ValueEnumerator, ImmutableStack.Enumerator, TSource, GetEnumerator, GetEnumerator2>(); - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator - : IFunction, ValueEnumerator> - { - public ValueEnumerator Invoke(ImmutableStack source) - => new(((IEnumerable)source).GetEnumerator()); - } - - [StructLayout(LayoutKind.Auto)] - public readonly struct GetEnumerator2 - : IFunction, ImmutableStack.Enumerator> - { - public ImmutableStack.Enumerator Invoke(ImmutableStack source) - => source.GetEnumerator(); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.Array.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.Array.cs deleted file mode 100644 index bedccd1e5..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.Array.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ArraySegmentValueEnumerableRef AsValueEnumerableRef(this TSource[] source) - => new(new ArraySegment(source)); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.ArraySegment.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.ArraySegment.cs deleted file mode 100644 index 0b6bc4f68..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.ArraySegment.cs +++ /dev/null @@ -1,412 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ArraySegmentValueEnumerableRef AsValueEnumerableRef(this ArraySegment source) - => new(source); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct ArraySegmentValueEnumerableRef - : IValueReadOnlyList.DisposableEnumerator> - , IList - { - internal readonly ArraySegment source; - - internal ArraySegmentValueEnumerableRef(ArraySegment source) - => this.source = source; - - public readonly int Count - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source.Count; - } - - public readonly ref TSource this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((uint)index >= (uint)source.Count) Throw.IndexOutOfRangeException(); - - return ref source.Array![source.Offset + index]; - } - } - TSource IReadOnlyList.this[int index] - => this[index]; - TSource IList.this[int index] - { - get => this[index]; - - [ExcludeFromCodeCoverage] - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SpanEnumeratorRef GetEnumerator() - => new(source); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(source); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(source); - - - bool ICollection.IsReadOnly - => true; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(Span span) - => source.AsSpan().CopyTo(span); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TSource[] array, int arrayIndex) - => Copy(source, array.AsSpan().Slice(arrayIndex)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource item) - => ((ICollection)source).Contains(item); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int IndexOf(TSource item) - => ArrayExtensions.IndexOf(source.AsSpan(), item); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - - [ExcludeFromCodeCoverage] - void IList.Insert(int index, TSource item) - => Throw.NotSupportedException(); - - [ExcludeFromCodeCoverage] - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly ArraySegment source; - int index; - - internal DisposableEnumerator(ArraySegment source) - { - this.source = source; - index = -1; - } - - public readonly ref TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((uint)index >= (uint)source.Count) Throw.IndexOutOfRangeException(); - - return ref source.Array![source.Offset + index]; - } - } - readonly TSource IEnumerator.Current - => this.Current; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => this.Current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index < source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ExcludeFromCodeCoverage] - public void Reset() - => index = -1; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void Dispose() { } - } - - #region Aggregation - - #endregion - - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentValueEnumerableRef AsEnumerable() - => this; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentValueEnumerableRef AsValueEnumerable() - => this; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TSource[] ToArray() - => source.AsSpan().ToArray(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.AsSpan().ToArray(memoryPool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.AsSpan().ToList(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(FunctionIn keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.AsSpan().ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - => source.AsSpan().ToDictionaryRef(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(FunctionIn keySelector, FunctionIn elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.AsSpan().ToDictionary(keySelector, elementSelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TElementSelector : struct, IFunctionIn - => source.AsSpan().ToDictionaryRef(keySelector, elementSelector, comparer); - - #endregion - - #region Element - - public Option ElementAt(int index) - => source.AsSpan().ElementAt(index); - - public Option First() - => source.AsSpan().First(); - - public Option Single() - => source.AsSpan().Single(); - - #endregion - - #region Filtering - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentWhereEnumerable> Where(FunctionIn predicate) - // => source.WhereRef(predicate); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentWhereEnumerable Where(TPredicate predicate = default) - // where TPredicate : struct, IFunctionIn - // => source.WhereRef(predicate); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentWhereAtEnumerable> Where(FunctionIn predicate) - // => source.WhereRef(predicate); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentWhereAtEnumerable WhereAt(TPredicate predicate = default) - // where TPredicate : struct, IFunctionIn - // => source.WhereAtRef(predicate); - - #endregion - - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentValueEnumerableRef Skip(int count) - { - var (skipCount, takeCount) = Utils.Skip(source.Count, count); - return new ArraySegmentValueEnumerableRef(new ArraySegment(source.Array!, source.Offset + skipCount, takeCount)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentValueEnumerableRef Take(int count) - => new(new ArraySegment(source.Array!, source.Offset, Utils.Take(source.Count, count))); - - #endregion - - #region Projection - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentSelectEnumerable> Select(FunctionIn selector) - // => source.SelectRef(selector); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentSelectEnumerable Select(TSelector selector = default) - // where TSelector : struct, IFunctionIn - // => source.SelectRef(selector); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentSelectAtEnumerable> Select(FunctionIn selector) - // => source.SelectRef(selector); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentSelectAtEnumerable SelectAt(TSelector selector = default) - // where TSelector : struct, IFunctionIn - // => source.SelectAtRef(selector); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentSelectManyEnumerable> SelectMany(FunctionIn selector) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // => source.SelectManyRef(selector); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ArraySegmentSelectManyEnumerable SelectMany(TSelector selector = default) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // where TSelector : struct, IFunctionIn - // => source.SelectManyRef(selector); - - #endregion - - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(FunctionIn predicate) - => All(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.AsSpan().AllRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(FunctionIn predicate) - => AllAt(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.AsSpan().AllAtRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.AsSpan().Any(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(FunctionIn predicate) - => Any(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.AsSpan().AnyRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(FunctionIn predicate) - => AnyAt(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.AsSpan().AnyAtRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource value, IEqualityComparer? comparer) - => source.AsSpan().Contains(value, comparer); - - #endregion - - #region Set - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentDistinctEnumerable Distinct(IEqualityComparer? comparer = default) - => source.Distinct(comparer); - - #endregion - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ArraySegmentValueEnumerableRef source) - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentValueEnumerableRef source) - => source.source.AsSpan().Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool ContainsVector(this ArraySegmentValueEnumerableRef source, TSource value) - where TSource : struct - => source.source.AsSpan().ContainsVector(value); - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static ArraySegmentSelectVectorEnumerable, Vector>, FunctionInWrapper> SelectVector(this ArraySegmentValueEnumerableRef source, FunctionIn, Vector> vectorSelector, FunctionIn selector) - // where TSource : struct - // where TResult : struct - // => source.source.SelectVector(vectorSelector, selector); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static ArraySegmentSelectVectorEnumerable SelectVector(this ArraySegmentValueEnumerableRef source, TSelector selector = default) - // where TSelector : struct, IFunctionIn, Vector>, IFunctionIn - // where TSource : struct - // where TResult : struct - // => source.source.SelectVector(selector, selector); - // - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static ArraySegmentSelectVectorEnumerable SelectVector(this ArraySegmentValueEnumerableRef source, TVectorSelector vectorSelector = default, TSelector selector = default) - // where TVectorSelector : struct, IFunctionIn, Vector> - // where TSelector : struct, IFunctionIn - // where TSource : struct - // where TResult : struct - // => source.source.SelectVector(vectorSelector, selector); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.Memory.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.Memory.cs deleted file mode 100644 index 1e3c7f5f4..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.Memory.cs +++ /dev/null @@ -1,367 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class MemoryBindings - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerableRef AsValueEnumerableRef(this Memory source) - => new(source); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct ValueEnumerableRef - : IValueReadOnlyList.DisposableEnumerator> - , IList - { - internal readonly Memory source; - - internal ValueEnumerableRef(Memory source) - => this.source = source; - - public readonly int Count - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source.Length; - } - - public readonly ref TSource this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source.Span[index]; - } - TSource IReadOnlyList.this[int index] - => source.Span[index]; - TSource IList.this[int index] - { - get => source.Span[index]; - - [ExcludeFromCodeCoverage] - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SpanEnumeratorRef GetEnumerator() - => new(source.Span); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(source); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(source); - - - bool ICollection.IsReadOnly - => true; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(Span span) - => source.Span.CopyTo(span); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TSource[] array, int arrayIndex) - => CopyTo(array.AsSpan(arrayIndex)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - bool ICollection.Contains(TSource item) - => source.Span.Contains(item); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int IndexOf(TSource item) - => ArrayExtensions.IndexOf(source.Span, item); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - - [ExcludeFromCodeCoverage] - void IList.Insert(int index, TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly Memory source; - int index; - - internal DisposableEnumerator(Memory source) - { - this.source = source; - index = -1; - } - - public readonly ref TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source.Span[index]; - } - readonly TSource IEnumerator.Current - => source.Span[index]; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => source.Span[index]; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index < source.Length; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ExcludeFromCodeCoverage] - public void Reset() - => index = -1; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void Dispose() { } - } - - #region Aggregation - - #endregion - - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableRef AsEnumerable() - => this; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableRef AsValueEnumerableRef() - => this; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Memory ToArray() - => source.Span.ToArray(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.Span.ToArray(memoryPool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.Span.ToList(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(FunctionIn keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.Span.ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - => source.Span.ToDictionaryRef(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(FunctionIn keySelector, FunctionIn elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.Span.ToDictionary(keySelector, elementSelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TElementSelector : struct, IFunctionIn - => source.Span.ToDictionaryRef(keySelector, elementSelector, comparer); - - #endregion - - #region Element - - public Option ElementAt(int index) - => source.Span.ElementAt(index); - - public Option First() - => source.Span.First(); - - public Option Single() - => source.Span.Single(); - - #endregion - - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArrayExtensions.MemoryWhereRefEnumerable> Where(FunctionIn predicate) - => source.Where(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArrayExtensions.MemoryWhereRefEnumerable Where(TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => source.WhereRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArrayExtensions.MemoryWhereAtRefEnumerable> Where(FunctionIn predicate) - => source.Where(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArrayExtensions.MemoryWhereAtRefEnumerable WhereAt(TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => source.WhereAtRef(predicate); - - #endregion - - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Memory Skip(int count) - => source.Skip(count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Memory Take(int count) - => source.Take(count); - - #endregion - - #region Projection - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectRefEnumerable> Select(FunctionIn selector) - // => source.Select(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectRefEnumerable Select(TSelector selector = default) - // where TSelector : struct, IFunctionIn - // => source.SelectRef(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectAtRefEnumerable> Select(FunctionIn selector) - // => source.Select(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectAtRefEnumerable SelectAt(TSelector selector = default) - // where TSelector : struct, IFunctionIn - // => source.SelectAtRef(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectManyRefEnumerable> SelectMany(FunctionIn selector) - // where TSubEnumerable : IValueEnumerableRef - // where TSubEnumerator : struct, IEnumerator - // => source.SelectMany(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectManyRefEnumerable SelectMany(TSelector selector = default) - // where TSubEnumerable : IValueEnumerableRef - // where TSubEnumerator : struct, IEnumerator - // where TSelector : struct, IFunctionIn - // => source.SelectManyRef(selector); - - #endregion - - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(FunctionIn predicate) - => source.Span.All(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.Span.AllRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(FunctionIn predicate) - => source.Span.All(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.Span.AllAtRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Span.Any(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(FunctionIn predicate) - => source.Span.Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.Span.AnyRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(FunctionIn predicate) - => source.Span.Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.Span.AnyAtRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource value, IEqualityComparer? comparer = null) - => source.Span.Contains(value, comparer); - - #endregion - - #region Set - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArrayExtensions.MemoryDistinctEnumerable Distinct(IEqualityComparer? comparer = default) - => ((ReadOnlyMemory)source).Distinct(comparer); - - #endregion - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.ReadOnlyMemory.cs deleted file mode 100644 index 7df64e2f5..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/AsValueEnumerableRef.ReadOnlyMemory.cs +++ /dev/null @@ -1,367 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyMemoryBindings - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerableRef AsValueEnumerableRef(this ReadOnlyMemory source) - => new(source); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct ValueEnumerableRef - : IValueReadOnlyList.DisposableEnumerator> - , IList - { - internal readonly ReadOnlyMemory source; - - internal ValueEnumerableRef(ReadOnlyMemory source) - => this.source = source; - - public readonly int Count - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source.Length; - } - - public readonly ref readonly TSource this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source.Span[index]; - } - TSource IReadOnlyList.this[int index] - => source.Span[index]; - TSource IList.this[int index] - { - get => source.Span[index]; - - [ExcludeFromCodeCoverage] - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlySpanEnumeratorRef GetEnumerator() - => new(source.Span); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(source); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(source); - - - bool ICollection.IsReadOnly - => true; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(Span span) - => source.Span.CopyTo(span); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TSource[] array, int arrayIndex) - => CopyTo(array.AsSpan(arrayIndex)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - bool ICollection.Contains(TSource item) - => source.Span.Contains(item); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int IndexOf(TSource item) - => ArrayExtensions.IndexOf(source.Span, item); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - - [ExcludeFromCodeCoverage] - void IList.Insert(int index, TSource item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly ReadOnlyMemory source; - int index; - - internal DisposableEnumerator(ReadOnlyMemory source) - { - this.source = source; - index = -1; - } - - public readonly ref readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source.Span[index]; - } - readonly TSource IEnumerator.Current - => source.Span[index]; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => source.Span[index]; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index < source.Length; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ExcludeFromCodeCoverage] - public void Reset() - => index = -1; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void Dispose() { } - } - - #region Aggregation - - #endregion - - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableRef AsEnumerable() - => this; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableRef AsValueEnumerableRef() - => this; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory ToArray() - => source.Span.ToArray(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.Span.ToArray(memoryPool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.Span.ToList(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(FunctionIn keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.Span.ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - => source.Span.ToDictionaryRef(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(FunctionIn keySelector, FunctionIn elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => source.Span.ToDictionary(keySelector, elementSelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TElementSelector : struct, IFunctionIn - => source.Span.ToDictionaryRef(keySelector, elementSelector, comparer); - - #endregion - - #region Element - - public Option ElementAt(int index) - => source.Span.ElementAt(index); - - public Option First() - => source.Span.First(); - - public Option Single() - => source.Span.Single(); - - #endregion - - #region Filtering - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemoryWhereRefEnumerable> Where(FunctionIn predicate) - // => source.Where(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemoryWhereRefEnumerable Where(TPredicate predicate = default) - // where TPredicate : struct, IFunctionIn - // => source.WhereRef(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemoryWhereAtRefEnumerable> Where(FunctionIn predicate) - // => source.Where(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemoryWhereAtRefEnumerable WhereAt(TPredicate predicate = default) - // where TPredicate : struct, IFunctionIn - // => source.WhereAtRef(predicate); - - #endregion - - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory Skip(int count) - => source.Skip(count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory Take(int count) - => source.Take(count); - - #endregion - - #region Projection - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectRefEnumerable> Select(FunctionIn selector) - // => source.Select(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectRefEnumerable Select(TSelector selector = default) - // where TSelector : struct, IFunctionIn - // => source.SelectRef(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectAtRefEnumerable> Select(FunctionIn selector) - // => source.Select(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectAtRefEnumerable SelectAt(TSelector selector = default) - // where TSelector : struct, IFunctionIn - // => source.SelectAtRef(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectManyRefEnumerable> SelectMany(FunctionIn selector) - // where TSubEnumerable : IValueEnumerableRef - // where TSubEnumerator : struct, IEnumerator - // => source.SelectMany(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArrayExtensions.MemorySelectManyRefEnumerable SelectMany(TSelector selector = default) - // where TSubEnumerable : IValueEnumerableRef - // where TSubEnumerator : struct, IEnumerator - // where TSelector : struct, IFunctionIn - // => source.SelectManyRef(selector); - - #endregion - - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(FunctionIn predicate) - => source.Span.All(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.Span.AllRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(FunctionIn predicate) - => source.Span.All(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.Span.AllAtRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Span.Any(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(FunctionIn predicate) - => source.Span.Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.Span.AnyRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(FunctionIn predicate) - => source.Span.Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source.Span.AnyAtRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TSource value, IEqualityComparer? comparer = null) - => source.Span.Contains(value, comparer); - - #endregion - - #region Set - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArrayExtensions.MemoryDistinctEnumerable Distinct(IEqualityComparer? comparer = default) - => source.Distinct(comparer); - - #endregion - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerableRef source) - => source.source.Span.Sum(); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/ReadOnlySpanEnumeratorRef.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/ReadOnlySpanEnumeratorRef.cs deleted file mode 100644 index cd67ad41a..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/ReadOnlySpanEnumeratorRef.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct ReadOnlySpanEnumeratorRef - { - readonly ReadOnlySpan source; - int index; - - internal ReadOnlySpanEnumeratorRef(ReadOnlySpan source) - { - this.source = source; - index = -1; - } - - public readonly ref readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index < source.Length; - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/SpanEnumeratorRef.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/SpanEnumeratorRef.cs deleted file mode 100644 index a0d6efa89..000000000 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerableRef/SpanEnumeratorRef.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct SpanEnumeratorRef - { - readonly Span source; - int index; - - internal SpanEnumeratorRef(Span source) - { - this.source = source; - index = -1; - } - - public readonly ref TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index < source.Length; - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ReadOnlyList.cs b/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ReadOnlyList.cs deleted file mode 100644 index 4fb246a66..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ReadOnlyList.cs +++ /dev/null @@ -1,258 +0,0 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TSource[] ToArray(this TList source) - where TList : struct, IReadOnlyList - => source.ToArray(0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] ToArray(this TList source, int offset, int count) - where TList : struct, IReadOnlyList - { - return count switch - { - 0 => Array.Empty(), - _ => BuildArray(source, offset, count) - }; - - static TSource[] BuildArray(TList source, int offset, int count) - { - var result = Utils.AllocateUninitializedArray(count); - Copy(source, offset, result.AsSpan(), count); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IMemoryOwner ToArray(this TList source, MemoryPool pool) - where TList : struct, IReadOnlyList - => source.ToArray(0, source.Count, pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this TList source, int offset, int count, MemoryPool pool) - where TList : struct, IReadOnlyList - { - return count switch - { - 0 => pool.Rent(0), - _ => BuildArray(source, offset, count, pool) - }; - - static IMemoryOwner BuildArray(TList source, int offset, int count, - MemoryPool pool) - { - var result = pool.RentSliced(count); - Copy(source, offset, result.Memory.Span, count); - return result; - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] ToArray(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - return count switch - { - 0 => Array.Empty(), - _ => BuildArray(source, predicate, offset, count) - }; - - static TSource[] BuildArray(TList source, TPredicate predicate, int offset, int count) - { - using var arrayBuilder = ToArrayBuilder(source, predicate, offset, count, ArrayPool.Shared); - return arrayBuilder.ToArray(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this TList source, TPredicate predicate, int offset, int count, MemoryPool pool) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - return count switch - { - 0 => pool.Rent(0), - _ => BuildArray(source, predicate, offset, count, pool) - }; - - static IMemoryOwner BuildArray(TList source, TPredicate predicate, int offset, int count, MemoryPool pool) - { - using var arrayBuilder = ToArrayBuilder(source, predicate, offset, count, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] ToArrayAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - return count switch - { - 0 => Array.Empty(), - _ => BuildArray(source, predicate, offset, count) - }; - - static TSource[] BuildArray(TList source, TPredicate predicate, int offset, int count) - { - using var arrayBuilder = ToArrayBuilderAt(source, predicate, offset, count, ArrayPool.Shared); - return arrayBuilder.ToArray(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayAt(this TList source, TPredicate predicate, int offset, int count, MemoryPool pool) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - return count switch - { - 0 => pool.Rent(0), - _ => BuildArray(source, predicate, offset, count, pool) - }; - - static IMemoryOwner BuildArray(TList source, TPredicate predicate, int offset, int count, MemoryPool pool) - { - using var arrayBuilder = ToArrayBuilderAt(source, predicate, offset, count, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArray(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - return count switch - { - 0 => Array.Empty(), - _ => BuildArray(source, selector, offset, count) - }; - - static TResult[] BuildArray(TList source, TSelector selector, int offset, int count) - { - var result = Utils.AllocateUninitializedArray(count); - Copy(source, offset, result.AsSpan(), count, selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this TList source, TSelector selector, int offset, int count, MemoryPool pool) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - return count switch - { - 0 => pool.Rent(0), - _ => BuildArray(source, selector, offset, count, pool) - }; - - static IMemoryOwner BuildArray(TList source, TSelector selector, int offset, int count, MemoryPool pool) - { - var result = pool.RentSliced(count); - Copy(source, offset, result.Memory.Span, count, selector); - return result; - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArrayAt(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - return count switch - { - 0 => Array.Empty(), - _ => BuildArray(source, selector, offset, count) - }; - - static TResult[] BuildArray(TList source, TSelector selector, int offset, int count) - { - var result = Utils.AllocateUninitializedArray(count); - CopyAt(source, offset, result.AsSpan(), count, selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayAt(this TList source, TSelector selector, int offset, int count, MemoryPool pool) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - return count switch - { - 0 => pool.Rent(0), - _ => BuildArray(source, selector, offset, count, pool) - }; - - static IMemoryOwner BuildArray(TList source, TSelector selector, int offset, int count, MemoryPool pool) - { - var result = pool.RentSliced(count); - CopyAt(source, offset, result.Memory.Span, count, selector); - return result; - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArray(this TList source, TPredicate predicate, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - return count switch - { - 0 => Array.Empty(), - _ => BuildArray(source, predicate, selector, offset, count) - }; - - static TResult[] BuildArray(TList source, TPredicate predicate, TSelector selector, int offset, int count) - { - using var arrayBuilder = ToArrayBuilder(source, predicate, selector, offset, count, ArrayPool.Shared); - return arrayBuilder.ToArray(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this TList source, TPredicate predicate, TSelector selector, int offset, int count, MemoryPool pool) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - return count switch - { - 0 => pool.Rent(0), - _ => BuildArray(source, predicate, selector, offset, count, pool) - }; - - static IMemoryOwner BuildArray(TList source, TPredicate predicate, TSelector selector, int offset, int count, MemoryPool pool) - { - using var arrayBuilder = ToArrayBuilder(source, predicate, selector, offset, count, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); - } - } - } -} - diff --git a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ReadOnlySpan.cs deleted file mode 100644 index bcee2ac54..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ReadOnlySpan.cs +++ /dev/null @@ -1,437 +0,0 @@ -using System; -using System.Buffers; -using System.Diagnostics; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IMemoryOwner ToArray(this ReadOnlySpan source, MemoryPool pool) - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, MemoryPool pool) - { - var result = pool.RentSliced(source.Length); - Copy(source, result.Memory.Span); - return result; - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] ToArray(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunction - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, predicate) - }; - - static TSource[] BuildArray(ReadOnlySpan source, TPredicate predicate) - { - using var arrayBuilder = ToArrayBuilder(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] ToArrayRef(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, predicate) - }; - - static TSource[] BuildArray(ReadOnlySpan source, TPredicate predicate) - { - using var arrayBuilder = ToArrayBuilderRef(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this ReadOnlySpan source, TPredicate predicate, MemoryPool pool) - where TPredicate : struct, IFunction - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, predicate, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TPredicate predicate, MemoryPool pool) - { - using var arrayBuilder = ToArrayBuilder(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayRef(this ReadOnlySpan source, TPredicate predicate, MemoryPool pool) - where TPredicate : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, predicate, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TPredicate predicate, MemoryPool pool) - { - using var arrayBuilder = ToArrayBuilderRef(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] ToArrayAt(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunction - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, predicate) - }; - - static TSource[] BuildArray(ReadOnlySpan source, TPredicate predicate) - { - using var arrayBuilder = ToArrayBuilderAt(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] ToArrayAtRef(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, predicate) - }; - - static TSource[] BuildArray(ReadOnlySpan source, TPredicate predicate) - { - using var arrayBuilder = ToArrayBuilderAtRef(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayAt(this ReadOnlySpan source, TPredicate predicate, MemoryPool pool) - where TPredicate : struct, IFunction - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, predicate, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TPredicate predicate, MemoryPool pool) - { - using var arrayBuilder = ToArrayBuilderAt(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayAtRef(this ReadOnlySpan source, TPredicate predicate, MemoryPool pool) - where TPredicate : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, predicate, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TPredicate predicate, MemoryPool pool) - { - using var arrayBuilder = ToArrayBuilderAtRef(source, predicate, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArray(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunction - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, selector) - }; - - static TResult[] BuildArray(ReadOnlySpan source, TSelector selector) - { - var result = Utils.AllocateUninitializedArray(source.Length); - Copy(source, result.AsSpan(), selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArrayVector(this ReadOnlySpan source, TVectorSelector vectorSelector, TSelector selector) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, vectorSelector, selector) - }; - - static TResult[] BuildArray(ReadOnlySpan source, TVectorSelector vectorSelector, TSelector selector) - { - var result = Utils.AllocateUninitializedArray(source.Length); - CopyVector(source, result.AsSpan(), vectorSelector, selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayVector(this ReadOnlySpan source, TVectorSelector vectorSelector, TSelector selector, MemoryPool pool) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, vectorSelector, selector, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TVectorSelector vectorSelector, TSelector selector, MemoryPool pool) - { - var result = pool.RentSliced(source.Length); - CopyVector(source, result.Memory.Span, vectorSelector, selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArrayRef(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, selector) - }; - - static TResult[] BuildArray(ReadOnlySpan source, TSelector selector) - { - var result = Utils.AllocateUninitializedArray(source.Length); - CopyRef(source, result.AsSpan(), selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this ReadOnlySpan source, TSelector selector, MemoryPool pool) - where TSelector : struct, IFunction - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, selector, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TSelector selector, MemoryPool pool) - { - var result = pool.RentSliced(source.Length); - Copy(source, result.Memory.Span, selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayRef(this ReadOnlySpan source, TSelector selector, MemoryPool pool) - where TSelector : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, selector, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TSelector selector, MemoryPool pool) - { - var result = pool.RentSliced(source.Length); - CopyRef(source, result.Memory.Span, selector); - return result; - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArrayAt(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunction - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, selector) - }; - - static TResult[] BuildArray(ReadOnlySpan source, TSelector selector) - { - var result = Utils.AllocateUninitializedArray(source.Length); - CopyAt(source, result.AsSpan(), selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArrayAtRef(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, selector) - }; - - static TResult[] BuildArray(ReadOnlySpan source, TSelector selector) - { - var result = Utils.AllocateUninitializedArray(source.Length); - CopyAtRef(source, result.AsSpan(), selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayAt(this ReadOnlySpan source, TSelector selector, MemoryPool pool) - where TSelector : struct, IFunction - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, selector, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TSelector selector, MemoryPool pool) - { - var result = pool.RentSliced(source.Length); - CopyAt(source, result.Memory.Span, selector); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayAtRef(this ReadOnlySpan source, TSelector selector, MemoryPool pool) - where TSelector : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, selector, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TSelector selector, MemoryPool pool) - { - var result = pool.RentSliced(source.Length); - CopyAtRef(source, result.Memory.Span, selector); - return result; - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArray(this ReadOnlySpan source, TPredicate predicate, TSelector selector) - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, predicate, selector) - }; - - static TResult[] BuildArray(ReadOnlySpan source, TPredicate predicate, TSelector selector) - { - using var arrayBuilder = ToArrayBuilder(source, predicate, selector, ArrayPool.Shared); - return arrayBuilder.ToArray(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArrayRef(this ReadOnlySpan source, TPredicate predicate, TSelector selector) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => Array.Empty(), - _ => BuildArray(source, predicate, selector) - }; - - static TResult[] BuildArray(ReadOnlySpan source, TPredicate predicate, TSelector selector) - { - using var arrayBuilder = ToArrayBuilderRef(source, predicate, selector, ArrayPool.Shared); - return arrayBuilder.ToArray(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this ReadOnlySpan source, TPredicate predicate, TSelector selector, MemoryPool pool) - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, predicate, selector, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TPredicate predicate, TSelector selector, MemoryPool pool) - { - using var arrayBuilder = ToArrayBuilder(source, predicate, selector, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayRef(this ReadOnlySpan source, TPredicate predicate, TSelector selector, MemoryPool pool) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - { - return source switch - { - { Length: 0 } => pool.Rent(0), - _ => BuildArray(source, predicate, selector, pool) - }; - - static IMemoryOwner BuildArray(ReadOnlySpan source, TPredicate predicate, TSelector selector, MemoryPool pool) - { - using var arrayBuilder = ToArrayBuilderRef(source, predicate, selector, ArrayPool.Shared); - return arrayBuilder.ToArray(pool); - } - } - } -} - diff --git a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.Span.cs b/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.Span.cs deleted file mode 100644 index f1d3b148b..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.Span.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Buffers; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IMemoryOwner ToArray(this Span source, MemoryPool pool) - => ((ReadOnlySpan)source).ToArray(pool); - } -} - diff --git a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ValueReadOnlyCollection.cs deleted file mode 100644 index afd1dfcd3..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToArray/ToArray.ValueReadOnlyCollection.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueReadOnlyCollectionExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TSource[] ToArray(this TEnumerable source) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - { - return source switch - { - { Count: 0 } => Array.Empty(), - ICollection collection => BuildArrayFromCollection(collection), - _ => BuildArray(source) - }; - - static TSource[] BuildArrayFromCollection(ICollection collection) - { - var result = Utils.AllocateUninitializedArray(collection.Count); - collection.CopyTo(result, 0); - return result; - } - - static TSource[] BuildArray(TEnumerable source) - { - var result = Utils.AllocateUninitializedArray(source.Count); - Copy(source, result); - return result; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IMemoryOwner ToArray(this TEnumerable source, MemoryPool pool) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - { - return source switch - { - { Count: 0 } => pool.Rent(0), - _ => BuildArray(source, pool) - }; - - static IMemoryOwner BuildArray(TEnumerable source, MemoryPool pool) - { - var result = pool.RentSliced(source.Count); - Copy(source, result.Memory.Span); - return result; - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] ToArray(this TEnumerable source, TPredicate predicate) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => source switch - { - { Count: 0 } => Array.Empty(), - _ => ValueEnumerableExtensions.ToArray(source, predicate) - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this TEnumerable source, TPredicate predicate, MemoryPool pool) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => source switch - { - { Count: 0 } => pool.Rent(0), - _ => ValueEnumerableExtensions.ToArray(source, predicate, pool) - }; - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] ToArrayAt(this TEnumerable source, TPredicate predicate) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => source switch - { - { Count: 0 } => Array.Empty(), - _ => ValueEnumerableExtensions.ToArrayAt(source, predicate) - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayAt(this TEnumerable source, TPredicate predicate, MemoryPool pool) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => source switch - { - { Count: 0 } => pool.Rent(0), - _ => ValueEnumerableExtensions.ToArrayAt(source, predicate, pool) - }; - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArray(this TEnumerable source, TSelector selector) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - return source switch - { - { Count: 0 } => Array.Empty(), - _ => BuildArray(source, selector) - }; - - static TResult[] BuildArray(TEnumerable source, TSelector selector) - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var array = new TResult[source.Count]; - Copy(source, array, selector); - return array; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this TEnumerable source, TSelector selector, MemoryPool pool) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - return source switch - { - { Count: 0 } => pool.Rent(0), - _ => BuildArray(source, selector, pool) - }; - - static IMemoryOwner BuildArray(TEnumerable source, TSelector selector, MemoryPool pool) - { - var result = pool.RentSliced(source.Count); - Copy(source, result.Memory.Span, selector); - return result; - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArrayAt(this TEnumerable source, TSelector selector) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - return source switch - { - { Count: 0 } => Array.Empty(), - _ => BuildArray(source, selector) - }; - - static TResult[] BuildArray(TEnumerable source, TSelector selector) - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var array = new TResult[source.Count]; - CopyAt(source, array, selector); - return array; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArrayAt(this TEnumerable source, TSelector selector, MemoryPool pool) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - return source switch - { - { Count: 0 } => pool.Rent(0), - _ => BuildArray(source, selector, pool) - }; - - static IMemoryOwner BuildArray(TEnumerable source, TSelector selector, MemoryPool pool) - { - var result = pool.RentSliced(source.Count); - CopyAt(source, result.Memory.Span, selector); - return result; - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TResult[] ToArray(this TEnumerable source, TPredicate predicate, TSelector selector) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - => source switch - { - { Count: 0 } => Array.Empty(), - _ => ValueEnumerableExtensions.ToArray(source, predicate, selector) - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static IMemoryOwner ToArray(this TEnumerable source, TPredicate predicate, TSelector selector, MemoryPool pool) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - => source switch - { - { Count: 0 } => pool.Rent(0), - _ => ValueEnumerableExtensions.ToArray(source, predicate, selector, pool) - }; - } -} diff --git a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ReadOnlyList.cs b/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ReadOnlyList.cs deleted file mode 100644 index 8266427bb..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ReadOnlyList.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this TList source, Func keySelector, IEqualityComparer? comparer = default) - where TList : struct, IReadOnlyList - where TKey : notnull - => source.ToDictionary(keySelector, comparer, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static Dictionary ToDictionary(this TList source, Func keySelector, IEqualityComparer? comparer, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - => source.ToDictionary>(new FunctionWrapper(keySelector), comparer, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this TList source, TKeySelector keySelector = default, IEqualityComparer? comparer = default) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - => source.ToDictionary(keySelector, comparer, 0, source.Count); - - static Dictionary ToDictionary(this TList source, TKeySelector keySelector, IEqualityComparer? comparer, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Count, comparer); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - dictionary.Add(keySelector.Invoke(item), item); - } - - return dictionary; - } - - static Dictionary ToDictionary(this TList source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - where TPredicate : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Count, comparer); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item)) - dictionary.Add(keySelector.Invoke(item), item); - } - return dictionary; - } - - - static Dictionary ToDictionaryAt(this TList source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - where TPredicate : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Count, comparer); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - dictionary.Add(keySelector.Invoke(item), item); - } - return dictionary; - } - - static Dictionary ToDictionary(this TList source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Count, comparer); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item)) - { - var result = selector.Invoke(item); - dictionary.Add(keySelector.Invoke(result), result); - } - } - return dictionary; - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this TList source, Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TList : struct, IReadOnlyList - where TKey : notnull - => source.ToDictionary(keySelector, elementSelector, comparer, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static Dictionary ToDictionary(this TList source, Func keySelector, Func elementSelector, IEqualityComparer? comparer, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - => source.ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this TList source, TKeySelector keySelector = default, TElementSelector elementSelector = default, IEqualityComparer? comparer = default) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => source.ToDictionary(keySelector, elementSelector, comparer, 0, source.Count); - - static Dictionary ToDictionary(this TList source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Count, comparer); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - dictionary.Add(keySelector.Invoke(item), elementSelector.Invoke(item)); - } - - return dictionary; - } - - static Dictionary ToDictionary(this TList source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - where TPredicate : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Count, comparer); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item)) - dictionary.Add(keySelector.Invoke(item), elementSelector.Invoke(item)); - } - return dictionary; - } - - static Dictionary ToDictionaryAt(this TList source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - where TPredicate : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Count, comparer); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - dictionary.Add(keySelector.Invoke(item), elementSelector.Invoke(item)); - } - return dictionary; - } - - static Dictionary ToDictionary(this TList source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Count, comparer); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item)) - { - var result = selector.Invoke(item); - dictionary.Add(keySelector.Invoke(result), elementSelector.Invoke(result)); - } - } - return dictionary; - } - - } -} - diff --git a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ReadOnlySpan.cs deleted file mode 100644 index 3c5c28376..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.ReadOnlySpan.cs +++ /dev/null @@ -1,300 +0,0 @@ - using System; -using System.Collections.Generic; - using System.Runtime.CompilerServices; - - namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this ReadOnlySpan source, Func keySelector, IEqualityComparer? comparer = null) - where TKey : notnull - => source.ToDictionary(new FunctionWrapper(keySelector), comparer); - - public static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer = null) - where TKey : notnull - where TKeySelector : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (var item in source) - dictionary.Add(keySelector.Invoke(item), item); - return dictionary; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this ReadOnlySpan source, FunctionIn keySelector, IEqualityComparer? comparer = null) - where TKey : notnull - => source.ToDictionaryRef(new FunctionInWrapper(keySelector), comparer); - - public static Dictionary ToDictionaryRef(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer = null) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (ref readonly var item in source) - dictionary.Add(keySelector.Invoke(in item), item); - return dictionary; - } - - static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) - where TKey : notnull - where TKeySelector : struct, IFunction - where TPredicate : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (var item in source) - { - if (predicate.Invoke(item)) - dictionary.Add(keySelector.Invoke(item), item); - } - return dictionary; - } - - static Dictionary ToDictionaryRef(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TPredicate : struct, IFunctionIn - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (ref readonly var item in source) - { - if (predicate.Invoke(in item)) - dictionary.Add(keySelector.Invoke(in item), item); - } - return dictionary; - } - - static Dictionary ToDictionaryAt(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) - where TKey : notnull - where TKeySelector : struct, IFunction - where TPredicate : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - for (var index = 0; index < source.Length; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - dictionary.Add(keySelector.Invoke(item), item); - } - return dictionary; - } - - static Dictionary ToDictionaryAtRef(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TPredicate : struct, IFunctionIn - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - for (var index = 0; index < source.Length; index++) - { - ref readonly var item = ref source[index]; - if (predicate.Invoke(in item, index)) - dictionary.Add(keySelector.Invoke(in item), item); - } - return dictionary; - } - - static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) - where TKey : notnull - where TKeySelector : struct, IFunction - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (var item in source) - { - if (predicate.Invoke(item)) - { - var result = selector.Invoke(item); - dictionary.Add(keySelector.Invoke(result), result); - } - } - return dictionary; - } - - static Dictionary ToDictionaryRef(this ReadOnlySpan source, TKeySelector keySelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (ref readonly var item in source) - { - if (predicate.Invoke(in item)) - { - var result = selector.Invoke(in item); - dictionary.Add(keySelector.Invoke(in result), result); - } - } - return dictionary; - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this ReadOnlySpan source, Func keySelector, Func elementSelector, IEqualityComparer? comparer = null) - where TKey : notnull - => source.ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - - public static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = null) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (var item in source) - dictionary.Add(keySelector.Invoke(item), elementSelector.Invoke(item)); - return dictionary; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this ReadOnlySpan source, FunctionIn keySelector, FunctionIn elementSelector, IEqualityComparer? comparer = null) - where TKey : notnull - => source.ToDictionaryRef, FunctionInWrapper>(new FunctionInWrapper(keySelector), new FunctionInWrapper(elementSelector), comparer); - - public static Dictionary ToDictionaryRef(this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = null) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TElementSelector : struct, IFunctionIn - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (ref readonly var item in source) - dictionary.Add(keySelector.Invoke(in item), elementSelector.Invoke(in item)); - return dictionary; - } - - static Dictionary - ToDictionary( - this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, - IEqualityComparer? comparer, TPredicate predicate) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - where TPredicate : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (var item in source) - { - if (predicate.Invoke(item)) - dictionary.Add(keySelector.Invoke(item), elementSelector.Invoke(item)); - } - return dictionary; - } - - static Dictionary - ToDictionaryRef( - this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, - IEqualityComparer? comparer, TPredicate predicate) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TElementSelector : struct, IFunctionIn - where TPredicate : struct, IFunctionIn - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (ref readonly var item in source) - { - if (predicate.Invoke(in item)) - dictionary.Add(keySelector.Invoke(in item), elementSelector.Invoke(in item)); - } - return dictionary; - } - - static Dictionary - ToDictionaryAt( - this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, - IEqualityComparer? comparer, TPredicate predicate) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - where TPredicate : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - for (var index = 0; index < source.Length; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - dictionary.Add(keySelector.Invoke(item), elementSelector.Invoke(item)); - } - - return dictionary; - } - - static Dictionary - ToDictionaryAtRef( - this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, - IEqualityComparer? comparer, TPredicate predicate) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TElementSelector : struct, IFunctionIn - where TPredicate : struct, IFunctionIn - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - for (var index = 0; index < source.Length; index++) - { - ref readonly var item = ref source[index]; - if (predicate.Invoke(in item, index)) - dictionary.Add(keySelector.Invoke(in item), elementSelector.Invoke(in item)); - } - - return dictionary; - } - - static Dictionary ToDictionary(this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (var item in source) - { - if (predicate.Invoke(item)) - { - var result = selector.Invoke(item); - dictionary.Add(keySelector.Invoke(result), elementSelector.Invoke(result)); - } - } - - return dictionary; - } - - static Dictionary ToDictionaryRef(this ReadOnlySpan source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer, TPredicate predicate, TSelector selector) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TElementSelector : struct, IFunctionIn - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - var dictionary = new Dictionary(source.Length, comparer); - foreach (var item in source) - { - if (predicate.Invoke(in item)) - { - var result = selector.Invoke(in item); - dictionary.Add(keySelector.Invoke(in result), elementSelector.Invoke(in result)); - } - } - - return dictionary; - } - } -} - diff --git a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.Span.cs b/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.Span.cs deleted file mode 100644 index bf4958bcc..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToDictionary/ToDictionary.Span.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this Span source, Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ((ReadOnlySpan)source).ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this Span source, TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => ((ReadOnlySpan)source).ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this Span source, FunctionIn keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ((ReadOnlySpan)source).ToDictionary(keySelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionaryRef(this Span source, TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - => ((ReadOnlySpan)source).ToDictionaryRef(keySelector, comparer); - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this Span source, Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ((ReadOnlySpan)source).ToDictionary(keySelector, elementSelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this Span source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => ((ReadOnlySpan)source).ToDictionary(keySelector, elementSelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionary(this Span source, FunctionIn keySelector, FunctionIn elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ((ReadOnlySpan)source).ToDictionary(keySelector, elementSelector, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Dictionary ToDictionaryRef(this Span source, TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunctionIn - where TElementSelector : struct, IFunctionIn - => ((ReadOnlySpan)source).ToDictionaryRef(keySelector, elementSelector, comparer); - } -} - diff --git a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ReadOnlyList.cs b/NetFabric.Hyperlinq/Conversion/ToList/ToList.ReadOnlyList.cs deleted file mode 100644 index 4fe06f879..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ReadOnlyList.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -// ReSharper disable HeapView.ObjectAllocation.Evident - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToList(this TList source, int offset, int count) - where TList : struct, IReadOnlyList - => source switch - { - { Count: 0 } => new List(), - _ => source.ToArray(offset, count).AsList() - }; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToList(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source switch - { - { Count: 0 } => new List(), - _ => source.ToArray(predicate, offset, count).AsList() - }; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source switch - { - { Count: 0 } => new List(), - _ => source.ToArrayAt(predicate, offset, count).AsList() - }; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToList(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => source switch - { - { Count: 0 } => new List(), - _ => source.ToArray(selector, offset, count).AsList() - }; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListAt(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => source switch - { - { Count: 0 } => new List(), - _ => source.ToArrayAt(selector, offset, count).AsList() - }; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToList(this TList source, TPredicate predicate, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - => source switch - { - { Count: 0 } => new List(), - _ => source.ToArray(predicate, selector, offset, count).AsList() - }; - } -} diff --git a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Conversion/ToList/ToList.ReadOnlySpan.cs deleted file mode 100644 index 49eb5d75d..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ReadOnlySpan.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Numerics; -using System.Runtime.CompilerServices; -// ReSharper disable HeapView.ObjectAllocation.Evident - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static List ToList(this ReadOnlySpan source) - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArray().AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToList(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunction - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArray(predicate).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListRef(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArrayRef(predicate).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListAt(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunction - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArrayAt(predicate).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListAtRef(this ReadOnlySpan source, TPredicate predicate) - where TPredicate : struct, IFunctionIn - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArrayAtRef(predicate).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToList(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunction - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArray(selector).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListVector(this ReadOnlySpan source, TVectorSelector vectorSelector, TSelector selector) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArrayVector(vectorSelector, selector).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListRef(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunctionIn - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArrayRef(selector).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListAt(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunction - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArrayAt(selector).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListAtRef(this ReadOnlySpan source, TSelector selector) - where TSelector : struct, IFunctionIn - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArrayAtRef(selector).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToList(this ReadOnlySpan source, TPredicate predicate, TSelector selector) - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArray(predicate, selector).AsList() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static List ToListRef(this ReadOnlySpan source, TPredicate predicate, TSelector selector) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => source switch - { - { Length: 0 } => new List(), - _ => source.ToArrayRef(predicate, selector).AsList() - }; - } -} diff --git a/NetFabric.Hyperlinq/Conversion/ToList/ToList.Span.cs b/NetFabric.Hyperlinq/Conversion/ToList/ToList.Span.cs deleted file mode 100644 index 9e378b0a7..000000000 --- a/NetFabric.Hyperlinq/Conversion/ToList/ToList.Span.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static List ToList(this Span source) - => ((ReadOnlySpan)source).ToList(); - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ReadOnlyList.cs b/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ReadOnlyList.cs deleted file mode 100644 index a1e77817a..000000000 --- a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.ReadOnlyList.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - public static Option ElementAt(this TList source, int index) - where TList : struct, IReadOnlyList - => source.ElementAt(index,0, source.Count); - - static Option ElementAt(this TList source, int index, int offset, int count) - where TList : struct, IReadOnlyList - => index < 0 || index >= count - ? Option.None - : Option.Some(source[index + offset]); - - - static Option ElementAt(this TList source, int index, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - if (index >= 0) - { - var end = offset + count; - for (var sourceIndex = offset; sourceIndex < end; sourceIndex++) - { - var item = source[sourceIndex]; - if (predicate.Invoke(item) && index-- is 0) - return Option.Some(item); - } - } - return Option.None; - } - - - static Option ElementAtAt(this TList source, int index, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - if (index >= 0) - { - if (offset is 0) - { - for (var sourceIndex = 0; sourceIndex < count; sourceIndex++) - { - var item = source[sourceIndex]; - if (predicate.Invoke(item, sourceIndex) && index-- is 0) - return Option.Some(item); - } - } - else - { - for (var sourceIndex = 0; sourceIndex < count; sourceIndex++) - { - var item = source[sourceIndex + offset]; - if (predicate.Invoke(item, sourceIndex) && index-- is 0) - return Option.Some(item); - } - } - } - return Option.None; - } - - - static Option ElementAt(this TList source, int index, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => index < 0 || index >= count - ? Option.None - : Option.Some(selector.Invoke(source[index + offset])); - - - static Option ElementAtAt(this TList source, int index, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => index < 0 || index >= count - ? Option.None - : Option.Some(selector.Invoke(source[index + offset], index)); - - - static Option ElementAt(this TList source, int index, TPredicate predicate, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - if (index >= 0) - { - var end = offset + count; - for (var sourceIndex = offset; sourceIndex < end; sourceIndex++) - { - var item = source[sourceIndex]; - if (predicate.Invoke(item) && index-- is 0) - return Option.Some(selector.Invoke(item)); - } - } - return Option.None; - } - } -} diff --git a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.Span.cs b/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.Span.cs deleted file mode 100644 index 43d0f7327..000000000 --- a/NetFabric.Hyperlinq/Element/ElementAt/ElementAt.Span.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Option ElementAt(this Span source, int index) - => ((ReadOnlySpan)source).ElementAt(index); - } -} diff --git a/NetFabric.Hyperlinq/Element/First/First.ReadOnlyList.cs b/NetFabric.Hyperlinq/Element/First/First.ReadOnlyList.cs deleted file mode 100644 index ef8add524..000000000 --- a/NetFabric.Hyperlinq/Element/First/First.ReadOnlyList.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - public static Option First(this TList source) - where TList : struct, IReadOnlyList - => source.First(0, source.Count); - - static Option First(this TList source, int offset, int count) - where TList : struct, IReadOnlyList - => count switch - { - 0 => Option.None, - _ => Option.Some(source[offset]), - }; - - - static Option First(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item)) - return Option.Some(item); - } - return Option.None; - } - - - static Option FirstAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - if (offset is 0) - { - for (var index = 0; index < count; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - return Option.Some(item); - } - } - else - { - for (var index = 0; index < count; index++) - { - var item = source[index + offset]; - if (predicate.Invoke(item, index)) - return Option.Some(item); - } - } - return Option.None; - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static Option First(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => count switch - { - 0 => Option.None, - _ => Option.Some(selector.Invoke(source[offset])), - }; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static Option FirstAt(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => count switch - { - 0 => Option.None, - _ => Option.Some(selector.Invoke(source[offset], 0)), - }; - - - static Option First(this TList source, TPredicate predicate, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - var end = offset + count; - for (var index = offset; index < end; index++) - { - if (predicate.Invoke(source[index])) - return Option.Some(selector.Invoke(source[index])); - } - return Option.None; - } - } -} diff --git a/NetFabric.Hyperlinq/Element/First/First.Span.cs b/NetFabric.Hyperlinq/Element/First/First.Span.cs deleted file mode 100644 index 4a1037d4a..000000000 --- a/NetFabric.Hyperlinq/Element/First/First.Span.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Option First(this Span source) - => ((ReadOnlySpan)source).First(); - } -} diff --git a/NetFabric.Hyperlinq/Element/Single/Single.ReadOnlyList.cs b/NetFabric.Hyperlinq/Element/Single/Single.ReadOnlyList.cs deleted file mode 100644 index 73870a923..000000000 --- a/NetFabric.Hyperlinq/Element/Single/Single.ReadOnlyList.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - public static Option Single(this TList source) - where TList : struct, IReadOnlyList - => source.Single(0, source.Count); - - static Option Single(this TList source, int offset, int count) - where TList : struct, IReadOnlyList - => count switch - { - 1 => Option.Some(source[offset]), - _ => Option.None, - }; - - - static Option Single(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source.GetSingle(predicate, offset, count); - - - static Option SingleAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source.GetSingleAt(predicate, offset, count); - - - static Option Single(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => count switch - { - 1 => Option.Some(selector.Invoke(source[offset])), - _ => Option.None, - }; - - - static Option SingleAt(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => count switch - { - 1 => Option.Some(selector.Invoke(source[offset], 0)), - _ => Option.None, - }; - - - static Option Single(this TList source, TPredicate predicate, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - => source.GetSingle(predicate, offset, count).Select(selector); - - //////////////////////////////// - // GetSingle - - - static Option GetSingle(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item)) - { - var value = item; - - for (index++; index < end; index++) - { - item = source[index]; - if (predicate.Invoke(item)) - return Option.None; - } - - return Option.Some(value); - } - } - - return Option.None; - } - - - static Option GetSingleAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - if (offset is 0) - { - for (var index = 0; index < count; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - { - var value = item; - - for (index++; index < count; index++) - { - item = source[index]; - if (predicate.Invoke(item, index)) - return Option.None; - } - - return Option.Some(value); - } - } - } - else - { - for (var index = 0; index < count; index++) - { - var item = source[index + offset]; - if (predicate.Invoke(item, index)) - { - var value = item; - - for (index++; index < count; index++) - { - item = source[index + offset]; - if (predicate.Invoke(item, index)) - return Option.None; - } - - return Option.Some(value); - } - } - } - - return Option.None; - } - } -} diff --git a/NetFabric.Hyperlinq/Element/Single/Single.Span.cs b/NetFabric.Hyperlinq/Element/Single/Single.Span.cs deleted file mode 100644 index 06e120ce0..000000000 --- a/NetFabric.Hyperlinq/Element/Single/Single.Span.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Option Single(this Span source) - => ((ReadOnlySpan)source).Single(); - } -} diff --git a/NetFabric.Hyperlinq/Filtering/Where/Where.ReadOnlyList.cs b/NetFabric.Hyperlinq/Filtering/Where/Where.ReadOnlyList.cs deleted file mode 100644 index 294522a7d..000000000 --- a/NetFabric.Hyperlinq/Filtering/Where/Where.ReadOnlyList.cs +++ /dev/null @@ -1,289 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereEnumerable> Where(this TList source, Func predicate) - where TList : struct, IReadOnlyList - => source.Where(predicate, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static WhereEnumerable> Where(this TList source, Func predicate, int offset, int count) - where TList : struct, IReadOnlyList - => source.Where>(new FunctionWrapper(predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereEnumerable Where(this TList source, TPredicate predicate = default) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source.Where(predicate, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static WhereEnumerable Where(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => new(in source, predicate, offset, count); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct WhereEnumerable - : IValueEnumerable.DisposableEnumerator> - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - readonly TList source; - readonly TPredicate predicate; - readonly int offset; - readonly int count; - - internal WhereEnumerable(in TList source, TPredicate predicate, int offset, int count) - => (this.source, this.offset, this.count, this.predicate) = (source, offset, count, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - { - readonly TList source; - TPredicate predicate; - readonly int end; - int index; - - internal Enumerator(in WhereEnumerable enumerable) - { - source = enumerable.source; - predicate = enumerable.predicate; - index = enumerable.offset - 1; - end = index + enumerable.count; - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (++index <= end) - { - if (predicate.Invoke(source[index])) - return true; - } - return false; - } - } - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly TList source; - TPredicate predicate; - readonly int end; - int index; - - internal DisposableEnumerator(in WhereEnumerable enumerable) - { - source = enumerable.source; - predicate = enumerable.predicate; - index = enumerable.offset - 1; - end = index + enumerable.count; - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source[index]; - } - - readonly TSource IEnumerator.Current - => source[index]; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => source[index]; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (++index <= end) - { - if (predicate.Invoke(source[index])) - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public readonly void Dispose() { } - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => source.Count(predicate, offset, count); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All() - => source.All(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => source.All>(new PredicatePredicateCombination(this.predicate, predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => source.AllAt>(new PredicatePredicateAtCombination(this.predicate, predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Any(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => source.Any>(new PredicatePredicateCombination(this.predicate, predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => source.AnyAt>(new PredicatePredicateAtCombination(this.predicate, predicate), offset, count); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereEnumerable, TSource>> Where(Func predicate) - => Where(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereEnumerable> Where(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => source.Where>(new PredicatePredicateCombination(this.predicate, predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable> WhereAt(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => source.WhereAt>(new PredicatePredicateAtCombination(this.predicate, predicate), offset, count); - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable Select(TSelector selector = default) - where TSelector : struct, IFunction - => source.WhereSelect(predicate, selector, offset, count); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => source.ElementAt(index, predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => source.First(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() -#pragma warning disable HLQ005 // Avoid Single() and SingleOrDefault() - => source.Single(predicate, offset, count); -#pragma warning restore HLQ005 // Avoid Single() and SingleOrDefault() - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TSource[] ToArray() - => source.ToArray(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.ToArray(predicate, offset, count, memoryPool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.ToList(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => source.ToDictionary(keySelector, comparer, predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => source.ToDictionary(keySelector, elementSelector, comparer, predicate, offset, count); - - #endregion - } - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/Where/Where.Span.cs b/NetFabric.Hyperlinq/Filtering/Where/Where.Span.cs deleted file mode 100644 index 7597f947b..000000000 --- a/NetFabric.Hyperlinq/Filtering/Where/Where.Span.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereEnumerable> Where(this Span source, Func predicate) - => source.Where(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereEnumerable Where(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunction - => ((ReadOnlySpan)source).Where(predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ReadOnlyList.cs b/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ReadOnlyList.cs deleted file mode 100644 index 055bc29e0..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ReadOnlyList.cs +++ /dev/null @@ -1,305 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereAtEnumerable> Where(this TList source, Func predicate) - where TList : struct, IReadOnlyList - => source.Where(predicate, 0, source.Count); - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static WhereAtEnumerable> Where(this TList source, Func predicate, int offset, int count) - where TList : struct, IReadOnlyList - => source.WhereAt>(new FunctionWrapper(predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereAtEnumerable WhereAt(this TList source, TPredicate predicate = default) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source.WhereAt(predicate, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static WhereAtEnumerable WhereAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => new(in source, predicate, offset, count); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct WhereAtEnumerable - : IValueEnumerable.DisposableEnumerator> - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - readonly TList source; - readonly TPredicate predicate; - readonly int offset; - readonly int count; - - internal WhereAtEnumerable(in TList source, TPredicate predicate, int offset, int count) - => (this.source, this.offset, this.count, this.predicate) = (source, offset, count, predicate); - - public readonly Enumerator GetEnumerator() - => new Enumerator(in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - { - readonly TList source; - TPredicate predicate; - readonly int offset; - readonly int end; - int index; - - internal Enumerator(in WhereAtEnumerable enumerable) - { - source = enumerable.source; - predicate = enumerable.predicate; - offset = enumerable.offset; - index = -1; - end = index + enumerable.count; - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source[index + offset]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (++index <= end) - { - if (predicate.Invoke(source[index + offset], index)) - return true; - } - return false; - } - } - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly TList source; - TPredicate predicate; - readonly int offset; - readonly int end; - int index; - - internal DisposableEnumerator(in WhereAtEnumerable enumerable) - { - source = enumerable.source; - predicate = enumerable.predicate; - offset = enumerable.offset; - index = -1; - end = index + enumerable.count; - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source[index + offset]; - } - readonly TSource IEnumerator.Current - => source[index + offset]; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => source[index + offset]; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (++index <= end) - { - if (predicate.Invoke(source[index + offset], index)) - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public readonly void Dispose() { } - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => source.CountAt(predicate, offset, count); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All() - => source.AllAt(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => source.AllAt>(new PredicatePredicateAtCombination(predicate, this.predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => source.AllAt>(new PredicateAtPredicateAtCombination(this.predicate, predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.AnyAt(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => source.AnyAt>(new PredicatePredicateAtCombination(predicate, this.predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => source.AnyAt>(new PredicateAtPredicateAtCombination(this.predicate, predicate), offset, count); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TPredicate, TSource>> Where(Func predicate) - => Where(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable> Where(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => source.WhereAt>(new PredicatePredicateAtCombination(predicate, this.predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable> WhereAt(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => source.WhereAt>(new PredicateAtPredicateAtCombination(this.predicate, predicate), offset, count); - - #endregion - #region Projection - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => source.ElementAtAt(index, predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => source.FirstAt(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() -#pragma warning disable HLQ005 // Avoid Single() and SingleOrDefault() - => source.SingleAt(predicate, offset, count); -#pragma warning restore HLQ005 // Avoid Single() and SingleOrDefault() - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TSource[] ToArray() - => source.ToArrayAt(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => source.ToArrayAt(predicate, offset, count, memoryPool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.ToListAt(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionaryAt>(new FunctionWrapper(keySelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionaryAt(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => source.ToDictionaryAt(keySelector, comparer, predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionaryAt, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionaryAt(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => source.ToDictionaryAt(keySelector, elementSelector, comparer, predicate, offset, count); - - #endregion - - public readonly bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } - } - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.Span.cs b/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.Span.cs deleted file mode 100644 index 9918c0983..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.Span.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereAtEnumerable> Where(this Span source, Func predicate) - => source.WhereAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereAtEnumerable WhereAt(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunction - => ((ReadOnlySpan)source).WhereAt(predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ValueReadOnlyCollection.cs deleted file mode 100644 index d467a8803..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAt/WhereAt.ValueReadOnlyCollection.cs +++ /dev/null @@ -1,306 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueReadOnlyCollectionExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereAtEnumerable> Where(this TEnumerable source, Func predicate) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => WhereAt>(source, new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static WhereAtEnumerable WhereAt(this TEnumerable source, TPredicate predicate = default) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => new(in source, predicate); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct WhereAtEnumerable - : IValueEnumerable.Enumerator> - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - { - internal readonly TEnumerable source; - internal readonly TPredicate predicate; - - internal WhereAtEnumerable(in TEnumerable source, TPredicate predicate) - => (this.source, this.predicate) = (source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly - TPredicate predicate; - int index; - - internal Enumerator(in WhereAtEnumerable enumerable) - { - enumerator = enumerable.source.GetEnumerator(); - predicate = enumerable.predicate; - index = -1; - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => enumerator.Current; - } - readonly TSource IEnumerator.Current - => enumerator.Current; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => enumerator.Current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - checked - { - while (enumerator.MoveNext()) - { - if (predicate.Invoke(enumerator.Current, ++index)) - return true; - } - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() - => enumerator.Dispose(); - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => ValueReadOnlyCollectionExtensions.CountAt(source, predicate); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All() - => ValueReadOnlyCollectionExtensions.AllAt(source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.AllAt>(source, new PredicatePredicateAtCombination(predicate, this.predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.AllAt>(source, new PredicateAtPredicateAtCombination(this.predicate, predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => ValueReadOnlyCollectionExtensions.AnyAt(source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.AnyAt>(source, new PredicatePredicateAtCombination(predicate, this.predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.AnyAt>(source, new PredicateAtPredicateAtCombination(this.predicate, predicate)); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TPredicate, TSource>> Where(Func predicate) - => Where(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable> Where(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.WhereAt>(source, new PredicatePredicateAtCombination(predicate, this.predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, TSource>> Where(Func predicate) - => WhereAt>(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable> WhereAt(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.WhereAt>(source, new PredicateAtPredicateAtCombination(this.predicate, predicate)); - - #endregion - #region Projection - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => ValueReadOnlyCollectionExtensions.ElementAtAt(source, index, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => ValueReadOnlyCollectionExtensions.FirstAt(source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() -#pragma warning disable HLQ005 // Avoid Single() and SingleOrDefault() - => ValueReadOnlyCollectionExtensions.SingleAt(source, predicate); -#pragma warning restore HLQ005 // Avoid Single() and SingleOrDefault() - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TSource[] ToArray() - => ValueReadOnlyCollectionExtensions.ToArrayAt(source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => ValueReadOnlyCollectionExtensions.ToArrayAt(source, predicate, memoryPool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => ValueReadOnlyCollectionExtensions.ToListAt(source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary(new FunctionWrapper(keySelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => ValueReadOnlyCollectionExtensions.ToDictionaryAt(source, keySelector, comparer, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => ValueReadOnlyCollectionExtensions.ToDictionaryAt(source, keySelector, elementSelector, comparer, predicate); - - #endregion - } - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static int Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, int, int, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static int Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, int?, int, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static long Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, long, long, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static long Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, long?, long, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static float Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, float, float, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static float Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, float?, float, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static double Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, double, double, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static double Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, double?, double, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static decimal Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, decimal, decimal, TPredicate>(source.predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public static decimal Sum(this WhereEnumerable source) - // where TEnumerable : IValueEnumerable - // where TEnumerator : struct, IEnumerator - // where TPredicate : struct, IFunction - // => source.Sum, WhereEnumerable.Enumerator, decimal?, decimal, TPredicate>(source.predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtReadOnlyRefEnumerator.cs b/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtReadOnlyRefEnumerator.cs deleted file mode 100644 index 49c89b6e1..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtReadOnlyRefEnumerator.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct WhereAtReadOnlyRefEnumerator - where TPredicate : struct, IFunctionIn - { - readonly ReadOnlySpan source; - TPredicate predicate; - int index; - - internal WhereAtReadOnlyRefEnumerator(ReadOnlySpan source, TPredicate predicate) - { - this.source = source; - this.predicate = predicate; - index = -1; - } - - public readonly ref readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - var span = source; - while (++index < span.Length) - { - if (predicate.Invoke(in span[index], index)) - return true; - } - return false; - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.ArraySegment.cs b/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.ArraySegment.cs deleted file mode 100644 index 42ebd0cfe..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.ArraySegment.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereAtRefEnumerable> Where(this in ArraySegment source, FunctionIn predicate) - => source.WhereAtRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereAtRefEnumerable WhereAtRef(this in ArraySegment source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly struct ArraySegmentWhereAtRefEnumerable - where TPredicate : struct, IFunctionIn - { - internal readonly ArraySegment source; - internal readonly TPredicate predicate; - - internal ArraySegmentWhereAtRefEnumerable(in ArraySegment source, TPredicate predicate) - => (this.source, this.predicate) = (source, predicate); - - public readonly WhereAtRefEnumerator GetEnumerator() - => new(source.AsSpan(), predicate); - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.Memory.cs b/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.Memory.cs deleted file mode 100644 index 63048db57..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.Memory.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemoryWhereAtRefEnumerable> Where(this Memory source, FunctionIn predicate) - => source.WhereAtRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemoryWhereAtRefEnumerable WhereAtRef(this Memory source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly struct MemoryWhereAtRefEnumerable - where TPredicate : struct, IFunctionIn - { - readonly Memory source; - readonly TPredicate predicate; - - internal MemoryWhereAtRefEnumerable(Memory source, TPredicate predicate) - => (this.source, this.predicate) = (source, predicate); - - public readonly WhereAtRefEnumerator GetEnumerator() - => new (source.Span, predicate); - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - } -} diff --git a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.ReadOnlyMemory.cs deleted file mode 100644 index 508400801..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.ReadOnlyMemory.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ReadOnlyMemoryWhereAtRefEnumerable> Where(this ReadOnlyMemory source, FunctionIn predicate) - => source.WhereAtRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ReadOnlyMemoryWhereAtRefEnumerable WhereAtRef(this ReadOnlyMemory source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly struct ReadOnlyMemoryWhereAtRefEnumerable - where TPredicate : struct, IFunctionIn - { - internal readonly ReadOnlyMemory source; - internal readonly TPredicate predicate; - - internal ReadOnlyMemoryWhereAtRefEnumerable(ReadOnlyMemory source, TPredicate predicate) - => (this.source, this.predicate) = (source, predicate); - - public readonly WhereAtReadOnlyRefEnumerator GetEnumerator() - => new (source.Span, predicate); - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlyMemoryWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumAtRef(source.predicate); - } -} diff --git a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.ReadOnlySpan.cs deleted file mode 100644 index 062441541..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.ReadOnlySpan.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpanWhereAtRefEnumerable> Where(this ReadOnlySpan source, FunctionIn predicate) - => source.WhereAtRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpanWhereAtRefEnumerable WhereAtRef(this ReadOnlySpan source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly ref struct ReadOnlySpanWhereAtRefEnumerable - where TPredicate : struct, IFunctionIn - { - internal readonly ReadOnlySpan source; - internal readonly TPredicate predicate; - - internal ReadOnlySpanWhereAtRefEnumerable(ReadOnlySpan source, TPredicate predicate) - { - this.source = source; - this.predicate = predicate; - } - - public readonly WhereAtReadOnlyRefEnumerator GetEnumerator() - => new (source, predicate); - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlySpanWhereAtRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumAtRef(source.predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.Span.cs b/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.Span.cs deleted file mode 100644 index 22b8dce8c..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRef.Span.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereAtRefEnumerable> Where(this Span source, FunctionIn predicate) - => source.WhereAtRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereAtRefEnumerable WhereAtRef(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly ref struct SpanWhereAtRefEnumerable - where TPredicate : struct, IFunctionIn - { - readonly Span source; - readonly TPredicate predicate; - - internal SpanWhereAtRefEnumerable(Span source, TPredicate predicate) - { - this.source = source; - this.predicate = predicate; - } - - public readonly WhereAtRefEnumerator GetEnumerator() - => new(source, predicate); - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRefEnumerator.cs b/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRefEnumerator.cs deleted file mode 100644 index ff6c12895..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereAtRef/WhereAtRefEnumerator.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct WhereAtRefEnumerator - where TPredicate : struct, IFunctionIn - { - readonly Span source; - TPredicate predicate; - int index; - - internal WhereAtRefEnumerator(Span source, TPredicate predicate) - { - this.source = source; - this.predicate = predicate; - index = -1; - } - - public readonly ref TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - var span = source; - while (++index < span.Length) - { - ref readonly var item = ref span[index]; - if (predicate.Invoke(in item, index)) - return true; - } - return false; - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereReadOnlyRefEnumerator.cs b/NetFabric.Hyperlinq/Filtering/WhereRef/WhereReadOnlyRefEnumerator.cs deleted file mode 100644 index 0e6312eec..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereReadOnlyRefEnumerator.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct WhereReadOnlyRefEnumerator - where TPredicate : struct, IFunctionIn - { - readonly ReadOnlySpan source; - TPredicate predicate; - int index; - - internal WhereReadOnlyRefEnumerator(ReadOnlySpan source, TPredicate predicate) - { - this.source = source; - this.predicate = predicate; - index = -1; - } - - public readonly ref readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - var span = source; - while (++index < span.Length) - { - if (predicate.Invoke(in span[index])) - return true; - } - return false; - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.ArraySegment.cs b/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.ArraySegment.cs deleted file mode 100644 index b3c62cbd6..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.ArraySegment.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereRefEnumerable> Where(this in ArraySegment source, FunctionIn predicate) - => source.WhereRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereRefEnumerable WhereRef(this in ArraySegment source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly struct ArraySegmentWhereRefEnumerable - where TPredicate : struct, IFunctionIn - { - internal readonly ArraySegment source; - internal readonly TPredicate predicate; - - internal ArraySegmentWhereRefEnumerable(in ArraySegment source, TPredicate predicate) - => (this.source, this.predicate) = (source, predicate); - - public readonly WhereRefEnumerator GetEnumerator() - => new(source.AsSpan(), predicate); - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => ((ReadOnlySpan)source.AsSpan()).CountRef(predicate); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All() - => ((ReadOnlySpan)source.AsSpan()).AllRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(FunctionIn predicate) - => All(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) - where TPredicate2 : struct, IFunctionIn - => ((ReadOnlySpan)source.AsSpan()).AllRef(new PredicatePredicateCombinationIn(this.predicate, predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(FunctionIn predicate) - => AllAt(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunctionIn - => ((ReadOnlySpan)source.AsSpan()).AllAtRef(new PredicatePredicateAtCombinationIn(this.predicate, predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => ((ReadOnlySpan)source.AsSpan()).AnyRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(FunctionIn predicate) - => Any(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) - where TPredicate2 : struct, IFunctionIn - => ((ReadOnlySpan)source.AsSpan()).AnyRef(new PredicatePredicateCombinationIn(this.predicate, predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(FunctionIn predicate) - => AnyAt(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunctionIn - => ((ReadOnlySpan)source.AsSpan()).AnyAtRef(new PredicatePredicateAtCombinationIn(this.predicate, predicate)); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereRefEnumerable, TSource>> Where(FunctionIn predicate) - => WhereRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereRefEnumerable> WhereRef(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunctionIn - => source.WhereRef(new PredicatePredicateCombinationIn(this.predicate, predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereAtRefEnumerable, TSource>> Where(FunctionIn predicate) - => WhereAtRef>(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereAtRefEnumerable> WhereAtRef(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunctionIn - => source.WhereAtRef(new PredicatePredicateAtCombinationIn(this.predicate, predicate)); - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereSelectRefEnumerable> Select(FunctionIn selector) - => Select>(new FunctionInWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegmentWhereSelectRefEnumerable Select(TSelector selector = default) - where TSelector : struct, IFunctionIn - => source.WhereSelectRef(predicate, selector); - - #endregion - - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.Memory.cs b/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.Memory.cs deleted file mode 100644 index 0ebc75733..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.Memory.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemoryWhereRefEnumerable> Where(this Memory source, FunctionIn predicate) - => source.WhereRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemoryWhereRefEnumerable WhereRef(this Memory source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly struct MemoryWhereRefEnumerable - where TPredicate : struct, IFunctionIn - { - readonly Memory source; - readonly TPredicate predicate; - - internal MemoryWhereRefEnumerable(Memory source, TPredicate predicate) - => (this.source, this.predicate) = (source, predicate); - - public readonly WhereRefEnumerator GetEnumerator() - => new(source.Span, predicate); - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.ReadOnlyMemory.cs deleted file mode 100644 index 5445d0bc1..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.ReadOnlyMemory.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ReadOnlyMemoryWhereRefEnumerable> Where(this ReadOnlyMemory source, FunctionIn predicate) - => source.WhereRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ReadOnlyMemoryWhereRefEnumerable WhereRef(this ReadOnlyMemory source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly struct ReadOnlyMemoryWhereRefEnumerable - where TPredicate : struct, IFunctionIn - { - internal readonly ReadOnlyMemory source; - internal readonly TPredicate predicate; - - internal ReadOnlyMemoryWhereRefEnumerable(ReadOnlyMemory source, TPredicate predicate) - => (this.source, this.predicate) = (source, predicate); - - public readonly WhereReadOnlyRefEnumerator GetEnumerator() - => new(source.Span, predicate); - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlyMemoryWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.Span.SumRef(source.predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.ReadOnlySpan.cs deleted file mode 100644 index 7bd92968b..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.ReadOnlySpan.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpanWhereRefEnumerable> Where(this ReadOnlySpan source, FunctionIn predicate) - => source.WhereRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpanWhereRefEnumerable WhereRef(this ReadOnlySpan source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly ref struct ReadOnlySpanWhereRefEnumerable - where TPredicate : struct, IFunctionIn - { - internal readonly ReadOnlySpan source; - internal readonly TPredicate predicate; - - internal ReadOnlySpanWhereRefEnumerable(ReadOnlySpan source, TPredicate predicate) - { - this.source = source; - this.predicate = predicate; - } - - public readonly WhereReadOnlyRefEnumerator GetEnumerator() - => new(source, predicate); - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ReadOnlySpanWhereRefEnumerable source) - where TPredicate : struct, IFunctionIn - => source.source.SumRef(source.predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.Span.cs b/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.Span.cs deleted file mode 100644 index f3abddba9..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRef.Span.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TPredicate", "NetFabric.Hyperlinq.FunctionInWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereRefEnumerable> Where(this Span source, FunctionIn predicate) - => source.WhereRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanWhereRefEnumerable WhereRef(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => new(source, predicate); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly ref struct SpanWhereRefEnumerable - where TPredicate : struct, IFunctionIn - { - readonly Span source; - readonly TPredicate predicate; - - internal SpanWhereRefEnumerable(Span source, TPredicate predicate) - { - this.source = source; - this.predicate = predicate; - } - - public readonly WhereRefEnumerator GetEnumerator() - => new (source, predicate); - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - if (Utils.UseDefault(comparer)) - { - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!EqualityComparer.Default.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - else - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRefEnumerator.cs b/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRefEnumerator.cs deleted file mode 100644 index c983219ba..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereRef/WhereRefEnumerator.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct WhereRefEnumerator - where TPredicate : struct, IFunctionIn - { - readonly Span source; - TPredicate predicate; - int index; - - internal WhereRefEnumerator(Span source, TPredicate predicate) - { - this.source = source; - this.predicate = predicate; - index = -1; - } - - public readonly ref TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref source[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - var span = source; - while (++index < span.Length) - { - ref readonly var item = ref span[index]; - if (predicate.Invoke(in item)) - return true; - } - return false; - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ReadOnlyList.cs b/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ReadOnlyList.cs deleted file mode 100644 index 37b76c326..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ReadOnlyList.cs +++ /dev/null @@ -1,326 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static WhereSelectEnumerable WhereSelect( - this TList source, - TPredicate predicate, - TSelector selector) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - => source.WhereSelect(predicate, selector, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static WhereSelectEnumerable WhereSelect( - this TList source, - TPredicate predicate, - TSelector selector, - int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - => new(source, predicate, selector, offset, count); - - [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct WhereSelectEnumerable - : IValueEnumerable.DisposableEnumerator> - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - readonly TList source; - readonly TPredicate predicate; - readonly TSelector selector; - readonly int offset; - readonly int count; - - internal WhereSelectEnumerable(TList source, TPredicate predicate, TSelector selector, int offset, int count) - => (this.source, this.offset, this.count, this.predicate, this.selector) = (source, offset, count, predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - { - readonly TList source; - TPredicate predicate; - TSelector selector; - readonly int end; - int index; - - internal Enumerator(in WhereSelectEnumerable enumerable) - { - source = enumerable.source; - predicate = enumerable.predicate; - selector = enumerable.selector; - index = enumerable.offset - 1; - end = index + enumerable.count; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(source[index]); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (++index <= end) - { - if (predicate.Invoke(source[index])) - return true; - } - return false; - } - } - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly TList source; - TPredicate predicate; - TSelector selector; - readonly int end; - int index; - - internal DisposableEnumerator(in WhereSelectEnumerable enumerable) - { - source = enumerable.source; - predicate = enumerable.predicate; - selector = enumerable.selector; - index = enumerable.offset - 1; - end = index + enumerable.count; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(source[index]); - } - TResult IEnumerator.Current - => selector.Invoke(source[index]); - object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(source[index]); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (++index <= end) - { - if (predicate.Invoke(source[index])) - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public readonly void Dispose() { } - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => source.Count(predicate, offset, count); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All() - => source.All(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.All, DisposableEnumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.AllAt, DisposableEnumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Any(predicate, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.Any, DisposableEnumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.AnyAt, DisposableEnumerator, TResult, TPredicate2>(predicate); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, WhereSelectEnumerable.DisposableEnumerator, TResult, FunctionWrapper> Where(Func predicate) - => this.Where, WhereSelectEnumerable.DisposableEnumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, WhereSelectEnumerable.DisposableEnumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => this.Where, WhereSelectEnumerable.DisposableEnumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, WhereSelectEnumerable.DisposableEnumerator, TResult, FunctionWrapper> Where(Func predicate) - => this.Where, WhereSelectEnumerable.DisposableEnumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, WhereSelectEnumerable.DisposableEnumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => this.WhereAt, WhereSelectEnumerable.DisposableEnumerator, TResult, TPredicate2>(predicate); - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.WhereSelect>(predicate, new SelectorSelectorCombination(this.selector, selector), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, WhereSelectEnumerable.DisposableEnumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, WhereSelectEnumerable.DisposableEnumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, WhereSelectEnumerable.DisposableEnumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, WhereSelectEnumerable.DisposableEnumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => source.ElementAt(index, predicate, selector, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => source.First(predicate, selector, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => source.Single(predicate, selector, offset, count); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => source.ToArray(predicate, selector, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.ToArray(predicate, selector, offset, count, pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.ToList(predicate, selector, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => source.ToDictionary(keySelector, comparer, predicate, selector, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => source.ToDictionary(keySelector, elementSelector, comparer, predicate, selector, offset, count); - - #endregion - - public readonly bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } - } - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ValueEnumerable.cs b/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ValueEnumerable.cs deleted file mode 100644 index cf5ed1118..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ValueEnumerable.cs +++ /dev/null @@ -1,258 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static WhereSelectEnumerable WhereSelect( - this TEnumerable source, - TPredicate predicate, - TSelector selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - => new(in source, predicate, selector); - - [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct WhereSelectEnumerable - : IValueEnumerable.Enumerator> - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - readonly TEnumerable source; - readonly TPredicate predicate; - readonly TSelector selector; - - internal WhereSelectEnumerable(in TEnumerable source, TPredicate predicate, TSelector selector) - { - this.source = source; - this.predicate = predicate; - this.selector = selector; - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() => - new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly - TPredicate predicate; - TSelector selector; - - internal Enumerator(in WhereSelectEnumerable enumerable) - { - enumerator = enumerable.source.GetEnumerator(); - predicate = enumerable.predicate; - selector = enumerable.selector; - } - - public TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(enumerator.Current); - } - TResult IEnumerator.Current - => selector.Invoke(enumerator.Current); - object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(enumerator.Current); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (enumerator.MoveNext()) - { - if (predicate.Invoke(enumerator.Current)) - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() - => enumerator.Dispose(); - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => source.Count(predicate); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All() - => source.All(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.All, Enumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.AllAt, Enumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.Any, Enumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.AnyAt, Enumerator, TResult, TPredicate2>(predicate); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereEnumerable, Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => this.Where, Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereEnumerable, Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => this.Where, Enumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => this.Where, Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereAtEnumerable, Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => this.WhereAt, Enumerator, TResult, TPredicate2>(predicate); - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.WhereSelect>(predicate, new SelectorSelectorCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => source.ElementAt(index, predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => source.First(predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => source.Single(predicate, selector); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => source.ToArray(predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.ToArray(predicate, selector, pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.ToList(predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary>(new FunctionWrapper(keySelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => source.ToDictionary(keySelector, comparer, predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => source.ToDictionary(keySelector, elementSelector, comparer, predicate, selector); - - #endregion - } - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ValueReadOnlyCollection.cs deleted file mode 100644 index 4c1c16816..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereSelect/WhereSelect.ValueReadOnlyCollection.cs +++ /dev/null @@ -1,258 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueReadOnlyCollectionExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static WhereSelectEnumerable WhereSelect( - this TEnumerable source, - TPredicate predicate, - TSelector selector) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - => new(in source, predicate, selector); - - [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct WhereSelectEnumerable - : IValueEnumerable.Enumerator> - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - where TSelector : struct, IFunction - { - readonly TEnumerable source; - readonly TPredicate predicate; - readonly TSelector selector; - - internal WhereSelectEnumerable(in TEnumerable source, TPredicate predicate, TSelector selector) - { - this.source = source; - this.predicate = predicate; - this.selector = selector; - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() => - new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly - TPredicate predicate; - TSelector selector; - - internal Enumerator(in WhereSelectEnumerable enumerable) - { - enumerator = enumerable.source.GetEnumerator(); - predicate = enumerable.predicate; - selector = enumerable.selector; - } - - public TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(enumerator.Current); - } - TResult IEnumerator.Current - => selector.Invoke(enumerator.Current); - object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(enumerator.Current); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (enumerator.MoveNext()) - { - if (predicate.Invoke(enumerator.Current)) - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() - => enumerator.Dispose(); - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => ValueReadOnlyCollectionExtensions.Count(source, predicate); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All() - => ValueReadOnlyCollectionExtensions.All(source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.All, Enumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All(Func predicate) - => AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AllAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.AllAt, Enumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => ValueReadOnlyCollectionExtensions.Any(source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.Any, Enumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate2 predicate) - where TPredicate2 : struct, IFunction - => this.AnyAt, Enumerator, TResult, TPredicate2>(predicate); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => ValueEnumerableExtensions.Where, Enumerator, TResult, TPredicate2>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) - where TPredicate2 : struct, IFunction - => ValueEnumerableExtensions.WhereAt, Enumerator, TResult, TPredicate2>(this, predicate); - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public WhereSelectEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.WhereSelect>(source, predicate, new SelectorSelectorCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableExtensions.SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => ValueEnumerableExtensions.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueEnumerableExtensions.SelectManyEnumerable, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => ValueEnumerableExtensions.SelectMany, Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(this, selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => ValueReadOnlyCollectionExtensions.ElementAt(source, index, predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => ValueReadOnlyCollectionExtensions.First(source, predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => ValueReadOnlyCollectionExtensions.Single(source, predicate, selector); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => ValueReadOnlyCollectionExtensions.ToArray(source, predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => ValueReadOnlyCollectionExtensions.ToArray(source, predicate, selector, pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => ValueReadOnlyCollectionExtensions.ToList(source, predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary(new FunctionWrapper(keySelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - => ValueReadOnlyCollectionExtensions.ToDictionary(source, keySelector, comparer, predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - => ToDictionary, FunctionWrapper>(new FunctionWrapper(keySelector), new FunctionWrapper(elementSelector), comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - where TKey : notnull - where TKeySelector : struct, IFunction - where TElementSelector : struct, IFunction - => ValueReadOnlyCollectionExtensions.ToDictionary(source, keySelector, elementSelector, comparer, predicate, selector); - - #endregion - } - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelectRef/WhereSelectReadOnlyRefEnumerator.cs b/NetFabric.Hyperlinq/Filtering/WhereSelectRef/WhereSelectReadOnlyRefEnumerator.cs deleted file mode 100644 index 6117d3786..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereSelectRef/WhereSelectReadOnlyRefEnumerator.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct WhereSelectReadOnlyRefEnumerator - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunction - { - readonly ReadOnlySpan source; - TPredicate predicate; - TSelector selector; - int index; - - internal WhereSelectReadOnlyRefEnumerator(ReadOnlySpan source, TPredicate predicate, TSelector selector) - { - this.source = source; - this.predicate = predicate; - this.selector = selector; - index = -1; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(source[index]); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - var span = source; - while (++index < span.Length) - { - if (predicate.Invoke(in span[index])) - return true; - } - return false; - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelectRef/WhereSelectRef.ArraySegment.cs b/NetFabric.Hyperlinq/Filtering/WhereSelectRef/WhereSelectRef.ArraySegment.cs deleted file mode 100644 index 8bfde6acc..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereSelectRef/WhereSelectRef.ArraySegment.cs +++ /dev/null @@ -1,312 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentWhereSelectRefEnumerable WhereSelectRef( - this ArraySegment source, - TPredicate predicate, - TSelector selector) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => new(source, predicate, selector); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct ArraySegmentWhereSelectRefEnumerable - : IValueEnumerable.Enumerator> - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - { - internal readonly ArraySegment source; - internal readonly TPredicate predicate; - internal readonly TSelector selector; - - internal ArraySegmentWhereSelectRefEnumerable(ArraySegment source, TPredicate predicate, TSelector selector) - => (this.source, this.predicate, this.selector) = (source, predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly WhereSelectRefEnumerator GetEnumerator() - => new(source.AsSpan(), predicate, selector); - readonly Enumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - readonly TSource[]? source; - TPredicate predicate; - TSelector selector; - readonly int end; - int index; - - internal Enumerator(in ArraySegmentWhereSelectRefEnumerable enumerable) - { - source = enumerable.source.Array; - predicate = enumerable.predicate; - selector = enumerable.selector; - index = enumerable.source.Offset - 1; - end = index + enumerable.source.Count; - } - - public readonly TResult Current - => selector.Invoke(in source![index]); - readonly TResult IEnumerator.Current - => selector.Invoke(in source![index]); - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(in source![index])!; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (++index <= end) - { - if (predicate.Invoke(in source![index])) - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() { } - } - - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => ((ReadOnlySpan)source.AsSpan()).CountRef(predicate); - - #endregion - #region Quantifier - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool All() - => ((ReadOnlySpan)source.AsSpan()).AllRef(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool All(Func predicate) - // => All(new FunctionInWrapper(predicate)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool All(TPredicate2 predicate) - // where TPredicate2 : struct, IFunctionIn - // => this.AllRef, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TPredicate2>(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool All(Func predicate) - // => AllAt(new FunctionInWrapper(predicate)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool AllAt(TPredicate2 predicate) - // where TPredicate2 : struct, IFunctionIn - // => this.AllAt, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TPredicate2>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => ((ReadOnlySpan)source.AsSpan()).AnyRef(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool Any(Func predicate) - // => Any(new FunctionInWrapper(predicate)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool Any(TPredicate2 predicate) - // where TPredicate2 : struct, IFunctionIn - // => this.AnyRef, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TPredicate2>(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool Any(Func predicate) - // => AnyAt(new FunctionInWrapper(predicate)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool AnyAt(TPredicate2 predicate) - // where TPredicate2 : struct, IFunctionIn - // => this.AnyAtRef, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TPredicate2>(predicate); - - #endregion - #region Filtering - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ValueEnumerableExtensions.WhereRefEnumerable, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, FunctionInWrapper> Where(FunctionIn predicate) - // => this.Where, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult>(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ValueEnumerableExtensions.WhereRefEnumerable, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TPredicate2> Where(TPredicate2 predicate = default) - // where TPredicate2 : struct, IFunctionIn - // => this.WhereRef, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TPredicate2>(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ValueEnumerableExtensions.WhereAtRefEnumerable, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, FunctionInWrapper> Where(FunctionIn predicate) - // => this.Where, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult>(predicate); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ValueEnumerableExtensions.WhereAtRefEnumerable, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TPredicate2> WhereAt(TPredicate2 predicate = default) - // where TPredicate2 : struct, IFunctionIn - // => this.WhereAtRef, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TPredicate2>(predicate); - - #endregion - #region Projection - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentWhereSelectRefEnumerable, TSource, TResult, TResult2>> Select(Func selector) - // => Select>(new FunctionInWrapper(selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentWhereSelectRefEnumerable> Select(TSelector2 selector = default) - // where TSelector2 : struct, IFunctionIn - // => source.WhereSelect>(predicate, new SelectorSelectorCombination(this.selector, selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ValueEnumerableExtensions.SelectManyEnumerable, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionInWrapper> SelectMany(Func selector) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // => this.SelectMany, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ValueEnumerableExtensions.SelectManyEnumerable, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // where TSelector2 : struct, IFunctionIn - // => this.SelectMany, ArraySegmentWhereSelectRefEnumerable.DisposableEnumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - #endregion - #region Element - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option ElementAt(int index) - // => source.ElementAtRef(index, predicate, selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option First() - // => source.FirstRef(predicate, selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option Single() - // => source.SingleRef(predicate, selector); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => ((ReadOnlySpan)source.AsSpan()).ToArrayRef(predicate, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool memoryPool) - => ((ReadOnlySpan)source.AsSpan()).ToArrayRef(predicate, selector, memoryPool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => ((ReadOnlySpan)source.AsSpan()).ToListRef(predicate, selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Dictionary ToDictionary(Func keySelector, IEqualityComparer? comparer = default) - // where TKey : notnull - // => ToDictionary>(new FunctionInWrapper(keySelector), comparer); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Dictionary ToDictionary(TKeySelector keySelector, IEqualityComparer? comparer = default) - // where TKey : notnull - // where TKeySelector : struct, IFunctionIn - // => source.ToDictionary(keySelector, comparer, predicate, selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Dictionary ToDictionary(Func keySelector, Func elementSelector, IEqualityComparer? comparer = default) - // where TKey : notnull - // => ToDictionary, FunctionInWrapper>(new FunctionInWrapper(keySelector), new FunctionInWrapper(elementSelector), comparer); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Dictionary ToDictionary(TKeySelector keySelector, TElementSelector elementSelector, IEqualityComparer? comparer = default) - // where TKey : notnull - // where TKeySelector : struct, IFunctionIn - // where TElementSelector : struct, IFunctionIn - // => source.ToDictionary(keySelector, elementSelector, comparer, predicate, selector); - - #endregion - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentWhereSelectRefEnumerable source) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.predicate, source.selector); - } -} - diff --git a/NetFabric.Hyperlinq/Filtering/WhereSelectRef/WhereSelectRefEnumerator.cs b/NetFabric.Hyperlinq/Filtering/WhereSelectRef/WhereSelectRefEnumerator.cs deleted file mode 100644 index 42a835ba3..000000000 --- a/NetFabric.Hyperlinq/Filtering/WhereSelectRef/WhereSelectRefEnumerator.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct WhereSelectRefEnumerator - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - { - readonly Span source; - TPredicate predicate; - TSelector selector; - int index; - - internal WhereSelectRefEnumerator(Span source, TPredicate predicate, TSelector selector) - { - this.source = source; - this.predicate = predicate; - this.selector = selector; - index = -1; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(in source[index]); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - var span = source; - while (++index < span.Length) - { - if (predicate.Invoke(in span[index])) - return true; - } - return false; - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Generator.AsValueEnumerable.cs b/NetFabric.Hyperlinq/Generator.AsValueEnumerable.cs new file mode 100644 index 000000000..99d722e67 --- /dev/null +++ b/NetFabric.Hyperlinq/Generator.AsValueEnumerable.cs @@ -0,0 +1,470 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using NetFabric.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + public partial class Generator + { + static ValueEnumerableType? GenerateSourceAsValueEnumerable(Compilation compilation, SemanticModel semanticModel, TypeSymbolsCache typeSymbolsCache, MemberAccessExpressionSyntax expressionSyntax, CodeBuilder builder, Dictionary generatedMethods, CancellationToken cancellationToken) + { + // Check if the method is already defined in the project source + if (semanticModel.GetSymbolInfo(expressionSyntax, cancellationToken).Symbol is IMethodSymbol { } methodSymbol) + return methodSymbol.ReturnType.ToValueEnumerableType(typeSymbolsCache); + + // Get the type this operator is applied to + var receiverTypeSymbol = semanticModel.GetTypeInfo(expressionSyntax.Expression, cancellationToken).Type; + + // Check if NetFabric.Hyperlinq already contains specific overloads for this type + // This is required for when the 'using NetFabric.Hyperlinq;' statement is missing + if (receiverTypeSymbol is null + or { TypeKind: TypeKind.Array } // is array + || SymbolEqualityComparer.Default.Equals(receiverTypeSymbol.OriginalDefinition, typeSymbolsCache[typeof(ArraySegment<>)]) + || SymbolEqualityComparer.Default.Equals(receiverTypeSymbol.OriginalDefinition, typeSymbolsCache[typeof(Span<>)]) + || SymbolEqualityComparer.Default.Equals(receiverTypeSymbol.OriginalDefinition, typeSymbolsCache[typeof(ReadOnlySpan<>)]) + || SymbolEqualityComparer.Default.Equals(receiverTypeSymbol.OriginalDefinition, typeSymbolsCache[typeof(Memory<>)]) + || SymbolEqualityComparer.Default.Equals(receiverTypeSymbol.OriginalDefinition, typeSymbolsCache[typeof(ReadOnlyMemory<>)]) + || SymbolEqualityComparer.Default.Equals(receiverTypeSymbol.OriginalDefinition, typeSymbolsCache[typeof(List<>)]) + || SymbolEqualityComparer.Default.Equals(receiverTypeSymbol.OriginalDefinition, typeSymbolsCache[typeof(ImmutableArray<>)]) + ) + return null; // Do generate an implementation. The 'using NetFabric.Hyperlinq;' statement should be added instead. + + // Receiver type implements IValueEnumerable<,> + + var valueEnumerableType = AsValueEnumerable(expressionSyntax, compilation, semanticModel, typeSymbolsCache, expressionSyntax, builder, generatedMethods, cancellationToken); + if (valueEnumerableType is not null) + { + // Check if the method is already defined by this generator + var methodSignature = new MethodSignature("AsValueEnumerable", valueEnumerableType.Name); + if (generatedMethods.TryGetValue(methodSignature, out var returnType)) + return returnType; + + // Receiver instance returns itself + _ = builder + .Line() + .GeneratedCodeMethodAttributes() + .AggressiveInliningAttribute() + .Line($"public static {valueEnumerableType.Name} AsValueEnumerable(this {valueEnumerableType.Name} source)") + .Indent().Line($"=> source;"); + + // A new AsValueEnumerable() method has been generated + generatedMethods.Add(methodSignature, valueEnumerableType); + return valueEnumerableType; + } + + // Receiver type is an enumerable + + if (receiverTypeSymbol.IsEnumerable(compilation, out var enumerableSymbols)) + { + var receiverTypeString = receiverTypeSymbol.ToDisplayString(); + + // Check if the method is already defined by this generator + var methodSignature = new MethodSignature("AsValueEnumerable", receiverTypeString); + if (generatedMethods.TryGetValue(methodSignature, out var returnType)) + return returnType; + + // Use an unique identifier to avoid name clashing + var uniqueIdString = builder.IsUnitTest + ? receiverTypeString.Replace('.', '_').Replace(',', '_').Replace('<', '_').Replace('>', '_').Replace('`', '_') + : Guid.NewGuid().ToString().Replace('-', '_'); // Use a GUID to avoid naming overflow + + var enumerableTypeString = $"AsValueEnumerable_{uniqueIdString}"; + var itemType = enumerableSymbols.EnumeratorSymbols.Current.Type; + var itemTypeString = itemType.ToDisplayString(); + + // Check if the returned type by GetEnumerator() does not require a wrapper + var getEnumeratorReturnType = enumerableSymbols.GetEnumerator.ReturnType; + var getEnumeratorReturnTypeString = getEnumeratorReturnType.ToDisplayString(); + + // Check what interfaces the enumerable implements, minimizing the calls to ImplementsInterface() + var enumerableIsIEnumerable = receiverTypeSymbol.ImplementsInterface(SpecialType.System_Collections_Generic_IEnumerable_T, out _); + var enumerableIsICollection = false; + var enumerableIsIReadOnlyCollection = false; + var enumerableIsIList = false; + var enumerableIsIReadOnlyList = false; + if (enumerableIsIEnumerable) + { + enumerableIsICollection = receiverTypeSymbol.ImplementsInterface(SpecialType.System_Collections_Generic_ICollection_T, out _); + if (enumerableIsICollection) + enumerableIsIList = receiverTypeSymbol.ImplementsInterface(SpecialType.System_Collections_Generic_IList_T, out _); + + enumerableIsIReadOnlyCollection = receiverTypeSymbol.ImplementsInterface(SpecialType.System_Collections_Generic_IReadOnlyCollection_T, out _); + if (enumerableIsIReadOnlyCollection) + enumerableIsIReadOnlyList = receiverTypeSymbol.ImplementsInterface(SpecialType.System_Collections_Generic_IReadOnlyList_T, out _); + } + + // Define what value enumerator type will be used + var enumeratorIsIEnumerator = getEnumeratorReturnType.ImplementsInterface(SpecialType.System_Collections_Generic_IEnumerator_T, out _); + + var enumeratorTypeString = enumeratorIsIEnumerator + ? getEnumeratorReturnType.IsValueType + ? getEnumeratorReturnTypeString + : $"ValueEnumerator<{itemTypeString}>" + : $"{enumerableTypeString}.Enumerator"; + + // Generate the method + _ = builder + .Line() + .GeneratedCodeMethodAttributes() + .AggressiveInliningAttribute() + .Line($"public static {enumerableTypeString} AsValueEnumerable(this {receiverTypeString} source)") + .Indent().Line($"=> new(source);"); + + // Generate the value enumerable wrapper + _ = builder + .Line() + .Line($"public readonly struct {enumerableTypeString}"); + + // Define what interfaces the wrapper implements + if (enumerableIsIList || enumerableIsIReadOnlyList) + _ = builder.Indent().Line($": IValueReadOnlyList<{itemTypeString}, {enumeratorTypeString}>, IList<{itemTypeString}>"); + else if (enumerableIsICollection || enumerableIsIReadOnlyCollection) + _ = builder.Indent().Line($": IValueReadOnlyCollection<{itemTypeString}, {enumeratorTypeString}>, ICollection<{itemTypeString}>"); + else + _ = builder.Indent().Line($": IValueEnumerable<{itemTypeString}, {enumeratorTypeString}>"); + + using (builder.Block()) + { + // Define field and constructor + _ = builder + .Line($"readonly {receiverTypeString} source;") + .Line() + .Line($"internal {enumerableTypeString}({receiverTypeString} source)") + .Indent().Line($"=> this.source = source;"); + + // Implement interfaces + ImplementIValueEnumerable(builder, enumerableSymbols, enumeratorTypeString, itemTypeString, enumeratorIsIEnumerator); + if (enumerableIsICollection || enumerableIsIReadOnlyCollection) + { + var sourceIsReferenceType = receiverTypeSymbol.IsReferenceType; + var itemIsReferenceType = itemType.IsReferenceType; + ImplementICollection(builder, itemTypeString, sourceIsReferenceType, itemIsReferenceType, enumerableIsICollection); + + if (enumerableIsIList || enumerableIsIReadOnlyList) + ImplementIList(builder, itemTypeString, sourceIsReferenceType, itemIsReferenceType, enumerableIsIList); + } + + // A new AsValueEnumerable() method has been generated + valueEnumerableType = new ValueEnumerableType( + Name: enumerableTypeString, + EnumeratorType: enumeratorTypeString, + ItemType: itemTypeString, + IsCollection: enumerableIsICollection || enumerableIsIReadOnlyCollection, + IsList: enumerableIsIList || enumerableIsIReadOnlyList); + generatedMethods.Add(methodSignature, valueEnumerableType); + return valueEnumerableType; + } + } + + return null; + } + + static void ImplementIValueEnumerable(CodeBuilder builder, EnumerableSymbols enumerableSymbols, string enumeratorTypeString, string itemTypeString, bool enumeratorIsIEnumerator) + { + var getEnumeratorReturnType = enumerableSymbols.GetEnumerator.ReturnType; + var getEnumeratorReturnTypeString = getEnumeratorReturnType.ToDisplayString(); + + _ = builder + .Line() + .Line($"// Implement IValueEnumerable<{itemTypeString}, {enumeratorTypeString}>") + .Line(); + + if (enumeratorIsIEnumerator) + { + if (getEnumeratorReturnType.IsValueType) + { + // No enumerator wrapper required + _ = builder + .AggressiveInliningAttribute() + .Line($"public {enumeratorTypeString} GetEnumerator() => source.GetEnumerator();") + .Line() + .Line($"IEnumerator<{itemTypeString}> IEnumerable<{itemTypeString}>.GetEnumerator() => GetEnumerator();") + .Line() + .Line($"IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();"); + } + else if (enumerableSymbols.GetEnumerator.ContainingType.IsInterface()) + { + // Use the ValueEnumerator<> enumerator wrapper + _ = builder + .AggressiveInliningAttribute() + .Line($"public ValueEnumerator<{itemTypeString}> GetEnumerator() => new(source.GetEnumerator());") + .Line() + .Line($"IEnumerator<{itemTypeString}> IEnumerable<{itemTypeString}>.GetEnumerator() => source.GetEnumerator();") + .Line() + .Line($"IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator();"); + } + else + { + // Use the ValueEnumerator<> enumerator wrapper + _ = builder + .AggressiveInliningAttribute() + .Line($"public ValueEnumerator<{itemTypeString}> GetEnumerator() => new(source.GetEnumerator());") + .Line() + .Line($"IEnumerator<{itemTypeString}> IEnumerable<{itemTypeString}>.GetEnumerator() => source.GetEnumerator();") + .Line() + .Line($"IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator();"); + } + } + else + { + // A custom enumerator wrapper is required + + _ = builder + .AggressiveInliningAttribute() + .Line($"public Enumerator GetEnumerator() => new(source.GetEnumerator());") + .Line() + .Line($"IEnumerator<{itemTypeString}> IEnumerable<{itemTypeString}>.GetEnumerator() => GetEnumerator();") + .Line() + .Line($"IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();") + .Line(); + + // define a value type enumerator wrapper + using (builder.Block($"public struct Enumerator : IEnumerator<{itemTypeString}>")) + { + _ = builder + .Line($"readonly {getEnumeratorReturnTypeString} source;") + .Line() + .Line($"internal Enumerator({getEnumeratorReturnTypeString} source)") + .Indent().Line("=> this.source = source;") + .Line() + .Line($"public {itemTypeString} Current") + .Line("{") + .Indent().AggressiveInliningAttribute() + .Indent().Line($"get => source.Current;") + .Line("}") + .Line() + .Line("object? IEnumerator.Current => source.Current;") + .Line() + .AggressiveInliningAttribute() + .Line("public bool MoveNext() => source.MoveNext();") + .Line(); + + _ = enumerableSymbols.EnumeratorSymbols.Reset is null + ? builder + .Line("public void Reset() => throw new NotSupportedException();") + : builder + .AggressiveInliningAttribute() + .Line("public void Reset() => source.Reset();"); + + _ = enumerableSymbols.EnumeratorSymbols.Dispose is null + ? builder + .Line() + .AggressiveInliningAttribute() + .Line("public void Dispose() { }") + : builder + .Line() + .AggressiveInliningAttribute() + .Line("public void Dispose() => source.Dispose();"); + } + } + } + + static void ImplementICollection(CodeBuilder builder, string itemTypeString, bool sourceIsReferenceType, bool itemIsReferenceType, bool sourceIsICollection) + { + _ = builder + .Line() + .Line($"// Implement ICollection<{itemTypeString}>") + .Line() + .Line("public int Count => source.Count;") + .Line() + .Line("public bool IsReadOnly => true;") + .Line() + .Line($"void ICollection<{itemTypeString}>.Add({itemTypeString} item) => throw new NotSupportedException();") + .Line() + .Line($"bool ICollection<{itemTypeString}>.Remove({itemTypeString} item) => throw new NotSupportedException();") + .Line() + .Line($"void ICollection<{itemTypeString}>.Clear() => throw new NotSupportedException();"); + + if (sourceIsICollection) + { + // Call the methods implemented by the source + _ = builder + .Line() + .AggressiveInliningAttribute() + .Line($"public bool Contains({itemTypeString} item) => source.Contains(item);") + .Line() + .AggressiveInliningAttribute() + .Line($"public void CopyTo({itemTypeString}[] array, int arrayIndex) => source.CopyTo(array, arrayIndex);"); + + return; // nothing else to do + } + + // The source does not implement these methods so we have to add an implementation + _ = builder + .Line() + .MethodBlock($"public bool Contains({itemTypeString} item)", + codeBuilder => + { + _ = codeBuilder + .Line("if (Count is 0)") + .Indent().Line("return false;"); + + if (sourceIsReferenceType) + { + _ = codeBuilder + .Line() + .Line($"if (source is ICollection<{itemTypeString}> collection)") + .Indent().Line("return collection.Contains(item);"); + } + + if (itemIsReferenceType) + { + _ = codeBuilder + .Line() + .Line($"var comparer = EqualityComparer<{itemTypeString}>.Default;") + .Line("using var enumerator = GetEnumerator();") + .WhileBlock("enumerator.MoveNext()", + codeBuilder => _ = codeBuilder + .Line("if (comparer.Equals(enumerator.Current, item))") + .Indent().Line("return true;") + ); + } + else // devirtualize the comparer + { + _ = codeBuilder + .Line() + .Line("using var enumerator = GetEnumerator();") + .WhileBlock("enumerator.MoveNext()", + codeBuilder => _ = codeBuilder + .Line($"if (EqualityComparer<{itemTypeString}>.Default.Equals(enumerator.Current, item))") + .Indent().Line("return true;") + ); + } + + _ = codeBuilder + .Line("return false;"); + }); + + _ = builder + .Line() + .MethodBlock($"public void CopyTo({itemTypeString}[] array, int arrayIndex)", + codeBuilder => + { + _ = codeBuilder + .Line("if (Count is 0)") + .Indent().Line("return;") + .Line() + .Line("if (array.Length - arrayIndex < Count)") + .Indent().Line($"throw new ArgumentException(\"{Resource.DestinationNotLongEnough}\", nameof(array));"); + + if (sourceIsReferenceType) + { + codeBuilder + .Line() + .IfBlock($"source is ICollection<{itemTypeString}> collection", + codeBuilder => _ = codeBuilder + .Line("collection.CopyTo(array, arrayIndex);") + .Line("return;")); + } + + _ = codeBuilder + .Line() + .Line("using var enumerator = GetEnumerator();") + .IfBlock( + "arrayIndex is 0 && array.Length == Count", // to enable range check elimination + codeBuilder => _ = codeBuilder + .Line( + "for (var index = 0; index < array.Length && enumerator.MoveNext(); index++)") + .Indent().Line("array[index] = enumerator.Current;"), + codeBuilder => _ = codeBuilder + .CheckedBlock( + codeBuilder => _ = codeBuilder + .Line( + "for (var index = arrayIndex; enumerator.MoveNext(); index++)") + .Indent().Line("array[index] = enumerator.Current;") + ) + ); + }); + } + + static void ImplementIList(CodeBuilder builder, string itemTypeString, bool sourceIsReferenceType, bool itemIsReferenceType, bool sourceIsIList) + { + _ = builder + .Line() + .Line($"// Implement IList<{itemTypeString}>") + .Line() + .Line($"public {itemTypeString} this[int index] => source[index];") + .Line(); + + using (builder.Block($"{itemTypeString} IList<{itemTypeString}>.this[int index]")) + { + _ = builder + .Line("get => source[index];") + .Line("set => throw new NotSupportedException();"); + } + + _ = builder + .Line() + .Line($"void IList<{itemTypeString}>.Insert(int index, {itemTypeString} item) => throw new NotSupportedException();") + .Line() + .Line($"void IList<{itemTypeString}>.RemoveAt(int index) => throw new NotSupportedException();") + .Line(); + + if (sourceIsIList) + { + // Call the methods implemented by the source + _ = builder + .AggressiveInliningAttribute() + .Line($"public int IndexOf({itemTypeString} item) => source.IndexOf(item);"); + + return; + } + + // The source does not implement these methods so we have to add an implementation + builder + .MethodBlock($"public int IndexOf({itemTypeString} item)", + codeBuilder => codeBuilder + .IfBlock("Count is not 0", + codeBuilder => + { + if (sourceIsReferenceType) + { + codeBuilder + .Line($"if (source is IList<{itemTypeString}> list)") + .Indent().Line("return list.IndexOf(item);") + .Line(); + } + + codeBuilder + .CheckedBlock( + codeBuilder => + { + if (itemIsReferenceType) + { + codeBuilder + .Line($"var comparer = EqualityComparer<{itemTypeString}>.Default;") + .Line("var index = 0;") + .ForEachBlock("var current in source", + codeBuilder => codeBuilder + .Line($"if (comparer.Equals(current, item))") + .Indent().Line("return index;") + .Line() + .Line("index++;") + ); + } + else // devirtualize the comparer + { + codeBuilder + .Line("var index = 0;") + .ForEachBlock("var current in source", + codeBuilder => codeBuilder + .Line( + $"if (EqualityComparer<{itemTypeString}>.Default.Equals(current, item))") + .Indent().Line("return index;") + .Line() + .Line("index++;") + ); + } + }); + }) + .Line("return -1;") + ); + } + + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Generator.cs b/NetFabric.Hyperlinq/Generator.cs new file mode 100644 index 000000000..8bebaa42d --- /dev/null +++ b/NetFabric.Hyperlinq/Generator.cs @@ -0,0 +1,349 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using NetFabric.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using System.Text; +using System.Threading; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + [Generator] + public partial class Generator + : ISourceGenerator + { + static readonly string assemblyName = typeof(CodeBuilder).Assembly.GetName().Name; + static readonly string assemblyVersion = typeof(CodeBuilder).Assembly.GetCustomAttribute()?.InformationalVersion ?? string.Empty; + + static readonly DiagnosticDescriptor unhandledExceptionError = new( + id: "HPLG001", + title: "Unhandled exception while generating overloads", + messageFormat: "Unhandled exception while generating overloads: {0}", + category: "OverloadsGenerator", + DiagnosticSeverity.Error, + isEnabledByDefault: true); + + internal static readonly ImmutableHashSet methods = ImmutableHashSet.Create(new[] + { + // aggregation + "Count", + "CountAsync", + "Sum", + "SumVector", + "SumAsync", + + // conversion + "AsEnumerable", + "AsAsyncEnumerable", + "AsValueEnumerable", + "AsAsyncValueEnumerable", + "ToArray", + "ToArrayVector", + "ToArrayAsync", + "ToDictionary", + "ToDictionaryAsync", + "ToList", + "ToListVector", + "ToListAsync", + + // element + "ElementAt", + "ElementAtAsync", + "First", + "FirstAsync", + "Single", + "SingleAsync", + + // filtering + "Where", + "WhereAsync", + + // partitioning + "Skip", + "SkipAsync", + "Take", + "TakeAsync", + + // projection + "Select", + "SelectVector", + "SelectAsync", + "SelectMany", + "SelectManyAsync", + + // quantifier + "All", + "AllAsync", + "Any", + "AnyAsync", + "Contains", + "ContainsVector", + "ContainsAsync", + + // quantifier + "Distinct", + "DistinctAsync", + }); + + static readonly ImmutableHashSet sumTypes = ImmutableHashSet.Create(new[] + { + "int", + "int?", + "nint", + "nint?", + "nuint", + "nuint?", + "long", + "long?", + "float", + "float?", + "double", + "double?", + "decimal", + "decimal?", + }); + + public void Initialize(GeneratorInitializationContext context) + { +#if DEBUG + if (!Debugger.IsAttached) + _ = Debugger.Launch(); +#endif + + context.RegisterForSyntaxNotifications(() => new SyntaxReceiver(methods)); + } + + public void Execute(GeneratorExecutionContext context) + { + var typeSymbolsCache = new TypeSymbolsCache(context.Compilation); + + // Check if NetFabric.Hyperlinq.Abstractions and NetFabric.Hyperlinq.Abstractions are referenced + if (typeSymbolsCache[typeof(IValueEnumerable<,>)] is null + || typeSymbolsCache[typeof(ValueEnumerableExtensions)] is null) + return; // TODO: return a Diagnostic? + + if (context.SyntaxReceiver is not SyntaxReceiver receiver) + return; + + try + { + var builder = new CodeBuilder(); + GenerateSource(context.Compilation, typeSymbolsCache, receiver.MemberAccessExpressions, builder, context.CancellationToken); + context.AddSource("ExtensionMethods.g.cs", SourceText.From(builder.ToString(), Encoding.UTF8)); + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + context.ReportDiagnostic(Diagnostic.Create(unhandledExceptionError, Location.None, ex.Message)); + } + } + + internal static void GenerateSource(Compilation compilation, TypeSymbolsCache typeSymbolsCache, List memberAccessExpressions, CodeBuilder builder, CancellationToken cancellationToken) + { + var generatedMethods = new Dictionary(); + + _ = builder + .Line("#nullable enable") + .Line() + .Line("using System;") + .Line("using System.CodeDom.Compiler;") + .Line("using System.Collections;") + .Line("using System.Collections.Generic;") + .Line("using System.ComponentModel;") + .Line("using System.Diagnostics;") + .Line("using System.Diagnostics.CodeAnalysis;") + .Line("using System.Runtime.CompilerServices;") + .Line() + .Line("namespace NetFabric.Hyperlinq;") + .Line(); + + using (builder.Block("static partial class GeneratedExtensionMethods")) + { + foreach (var expressionSyntax in memberAccessExpressions) + { + cancellationToken.ThrowIfCancellationRequested(); + + var semanticModel = compilation.GetSemanticModel(expressionSyntax.SyntaxTree); + + _ = GenerateSource(compilation, semanticModel, typeSymbolsCache, expressionSyntax, builder, generatedMethods, cancellationToken); + } + } + } + + static ValueEnumerableType? AsValueEnumerable(MemberAccessExpressionSyntax memberAccessExpressionSyntax, Compilation compilation, SemanticModel semanticModel, TypeSymbolsCache typeSymbolsCache, MemberAccessExpressionSyntax expressionSyntax, CodeBuilder builder, Dictionary generatedMethods, CancellationToken cancellationToken) + { + var typeSymbol = semanticModel.GetTypeInfo(memberAccessExpressionSyntax.Expression, cancellationToken).Type; + if (typeSymbol is null) + return null; + + // Check if the receiver type implements IValueEnumerable<,> + var valueEnumerableType = typeSymbol.ToValueEnumerableType(typeSymbolsCache); + if (valueEnumerableType is not null) + return valueEnumerableType; + + // Go up one layer. Generate method if required. + if (expressionSyntax.Expression is InvocationExpressionSyntax { Expression: MemberAccessExpressionSyntax receiverSyntax }) + { + valueEnumerableType = GenerateSource(compilation, semanticModel, typeSymbolsCache, receiverSyntax, builder, generatedMethods, cancellationToken); + if (valueEnumerableType is not null) + return valueEnumerableType; + } + + // Receiver type does not implement IValueEnumerable<,> so nothing else needs to be done + return null; + } + + static ValueEnumerableType? GenerateSource(Compilation compilation, SemanticModel semanticModel, TypeSymbolsCache typeSymbolsCache, MemberAccessExpressionSyntax expressionSyntax, CodeBuilder builder, Dictionary generatedMethods, CancellationToken cancellationToken) + => expressionSyntax.Name.ToString() switch + { + "AsValueEnumerable" => GenerateSourceAsValueEnumerable(compilation, semanticModel, typeSymbolsCache, expressionSyntax, builder, generatedMethods, cancellationToken), + _ => GenerateSourceDefault(compilation, semanticModel, typeSymbolsCache, expressionSyntax, builder, generatedMethods, cancellationToken), + }; + + static ValueEnumerableType? GenerateSourceDefault(Compilation compilation, SemanticModel semanticModel, TypeSymbolsCache typeSymbolsCache, MemberAccessExpressionSyntax expressionSyntax, CodeBuilder builder, Dictionary generatedMethods, CancellationToken cancellationToken) + { + // Find the receiver type + var receiverType = AsValueEnumerable(expressionSyntax, compilation, semanticModel, typeSymbolsCache, expressionSyntax, builder, generatedMethods, cancellationToken); + if (receiverType is null) + return null; + + var methodName = expressionSyntax.Name.ToString(); + if (methodName == "Sum" && !sumTypes.Contains(receiverType.ItemType)) + return null; + + var containingClass = receiverType.IsList + ? typeSymbolsCache[typeof(ValueReadOnlyListExtensions)]! + : receiverType.IsCollection + ? typeSymbolsCache[typeof(ValueReadOnlyCollectionExtensions)]! + : typeSymbolsCache[typeof(ValueEnumerableExtensions)]!; + var containingClassString = containingClass.ToDisplayString(); + + // Check if the method is already defined + var symbol = semanticModel.GetSymbolInfo(expressionSyntax, cancellationToken).Symbol; + if (symbol is IMethodSymbol methodSymbol) + { + // If it's an instance method of a type that implements IValueEnumerable<,> then it's already optimized. + if (methodSymbol.ReceiverType is not null && methodSymbol.ReceiverType.ImplementsInterface(typeSymbolsCache[typeof(IValueEnumerable<,>)]!, out _)) + return methodSymbol.ReturnType.ToValueEnumerableType(typeSymbolsCache); // return the returned type + + // Check if the generator already generated the extension method + var parameters = methodSymbol.Parameters.Select(parameter => parameter.Type.ToDisplayString()) + .ToArray(); + var methodSignature = + new MethodSignature(expressionSyntax.Name.ToString(), receiverType.Name, parameters); + if (generatedMethods.TryGetValue(methodSignature, out var returnType)) + return returnType; + + // Generate the extension method + var comparer = new TypeSymbolConversionComparer(compilation); + var parametersTypes = methodSymbol.Parameters.Select(parameter => parameter.Type).ToArray(); + var hyperlinqMethods = containingClass + .GetMembers() + .OfType() + .Where(method => + method.IsPublic() + && method.Name == methodName + && method.Parameters.Skip(1).Select(parameter => parameter.Type).SequenceEqual(parametersTypes, comparer)) + .ToArray(); + var hyperlinqMethod = hyperlinqMethods.FirstOrDefault(); + if (hyperlinqMethod is null) + return null; + + var parametersString = string.Join(", ", + new[] { $"{receiverType.Name} source" } + .Concat(methodSymbol.Parameters.Select(static parameter => $"{parameter.Type.ToDisplayString()} {parameter.Name}"))); + var argumentsString = string.Join(", ", + new[] { "source" } + .Concat(methodSymbol.Parameters.Select(parameter => MapArgument(parameter, typeSymbolsCache)))); + var typeArgumentsString = string.Join(", ", + new[] { receiverType.Name, receiverType.EnumeratorType } + .Concat(methodSymbol.TypeArguments.Select(argument => MapTypeArgument(argument, typeSymbolsCache)))); + var returnTypeString = hyperlinqMethod.ReturnType is INamedTypeSymbol { IsGenericType: true } + ? $"{hyperlinqMethod.ReturnType.ContainingType}.{hyperlinqMethod.ReturnType.Name}<{typeArgumentsString}>" + : hyperlinqMethod.ReturnType.ToDisplayString(); + _ = builder + .Line() + .GeneratedCodeMethodAttributes() + .Line("[MethodImpl(MethodImplOptions.AggressiveInlining)]") + .Line($"public static {returnTypeString} {methodSymbol.Name}(this {parametersString})") + .Indent() + .Line($"=> {containingClassString}.{methodSymbol.Name}<{typeArgumentsString}>({argumentsString});"); + } + + // The method is not yet defined + if (expressionSyntax.Parent is InvocationExpressionSyntax invocation) + { + var a = invocation.ArgumentList.Arguments + .Select(argument => semanticModel.GetTypeInfo(argument.Expression).Type) + .ToArray(); + // Check if the generator already generated the extension method + //var parameters = new string[] { receiverType.Name }.Concat(invocation.ArgumentList.Arguments.Select(argument => argument.ToDisplayString())).ToArray(); + //var methodSignature = new MethodSignature(expressionSyntax.Name.ToString(), parameters); + //if (generatedMethods.TryGetValue(methodSignature, out var returnType)) + // return returnType; + + //// Generate the extension method + //var hyperlinqMethod = hyperlinqMethods.FirstOrDefault(); + + //var parametersString = string.Join(", ", + // new string[] { $"{receiverType.Name} source" } + // .Concat(methodSymbol.Parameters.Select(parameter => $"{parameter.Type.ToDisplayString()} {parameter.Name}"))); + //var argumentsString = string.Join(", ", + // new string[] { "source" } + // .Concat(methodSymbol.Parameters.Select(parameter => parameter.Name))); + //_ = builder + // .Line() + // .Line("[MethodImpl(MethodImplOptions.AggressiveInlining)]") + // .Line($"public static {hyperlinqMethod.ReturnType.ToDisplayString()} {methodSymbol.Name}(this {parametersString})") + // .Indent().Line($"=> {containingClassString}.{methodSymbol.Name}<{receiverType.Name}, {receiverType.EnumeratorType}, {receiverType.ItemType}>({argumentsString});"); + + //generatedMethods.Add(methodSignature, returnType); + //return returnType; + } + + return null; + + static string MapArgument(IParameterSymbol parameter, TypeSymbolsCache typeSymbolsCache) + { + if (parameter.Type is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) + { + // Convert Func<> to FunctionWrapper<> + if (SymbolEqualityComparer.Default.Equals(parameter.Type.OriginalDefinition, typeSymbolsCache[typeof(Func<,>)])) + { + var typeArguments = string.Join(", ", + namedTypeSymbol.TypeArguments.Select(argument => argument.ToDisplayString())); + return $"new NetFabric.Hyperlinq.FunctionWrapper<{typeArguments}>({parameter.Name})"; + } + } + + return parameter.Name; + } + + static string MapTypeArgument(ITypeSymbol argument, TypeSymbolsCache typeSymbolsCache) + { + if (argument is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) + { + // Convert Func<> to FunctionWrapper<> + if (SymbolEqualityComparer.Default.Equals(argument.OriginalDefinition, typeSymbolsCache[typeof(Func<,>)])) + { + var typeArguments = string.Join(", ", + namedTypeSymbol.TypeArguments.Select(argument => argument.ToDisplayString())); + return $"NetFabric.Hyperlinq.FunctionWrapper<{typeArguments}>"; + } + } + + return argument.ToDisplayString(); + } + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/ITypeSymbolExtensions.cs b/NetFabric.Hyperlinq/ITypeSymbolExtensions.cs new file mode 100644 index 000000000..596bdd104 --- /dev/null +++ b/NetFabric.Hyperlinq/ITypeSymbolExtensions.cs @@ -0,0 +1,53 @@ +using Microsoft.CodeAnalysis; +using NetFabric.CodeAnalysis; +using System.Collections.Immutable; +using System.Runtime.CompilerServices; + +// ReSharper disable LoopCanBeConvertedToQuery + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + static class ITypeSymbolExtensions + { + public static bool ImplementsAnyInterface(this ITypeSymbol typeSymbol, INamedTypeSymbol[] interfaceTypes, out ImmutableArray genericArguments) + { + if (typeSymbol is INamedTypeSymbol namedTypeSymbol) + { + foreach (var interfaceType in interfaceTypes) + { + if (SymbolEqualityComparer.Default.Equals(namedTypeSymbol.OriginalDefinition, interfaceType)) + { + genericArguments = namedTypeSymbol.TypeArguments; + return true; + } + } + } + + // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator + foreach (var @interface in typeSymbol.AllInterfaces) + { + foreach (var interfaceType in interfaceTypes) + { + if (SymbolEqualityComparer.Default.Equals(@interface.OriginalDefinition, interfaceType)) + { + genericArguments = @interface.TypeArguments; + return true; + } + } + } + + Unsafe.SkipInit(out genericArguments); + return false; + } + + public static ValueEnumerableType? ToValueEnumerableType(this ITypeSymbol typeSymbol, TypeSymbolsCache typeSymbolsCache) + => !typeSymbol.ImplementsInterface(typeSymbolsCache[typeof(IValueEnumerable<,>)]!, out var genericArguments) + ? null + : new ValueEnumerableType( + Name: typeSymbol.ToDisplayString(), + EnumeratorType: genericArguments[1].ToDisplayString(), + ItemType: genericArguments[0].ToDisplayString(), + IsCollection: typeSymbol.ImplementsInterface(typeSymbolsCache[typeof(IValueReadOnlyCollection<,>)]!, out _), + IsList: typeSymbol.ImplementsInterface(typeSymbolsCache[typeof(IValueReadOnlyList<,>)]!, out _)); + } +} diff --git a/NetFabric.Hyperlinq/MethodSignature.cs b/NetFabric.Hyperlinq/MethodSignature.cs new file mode 100644 index 000000000..cdd27a357 --- /dev/null +++ b/NetFabric.Hyperlinq/MethodSignature.cs @@ -0,0 +1,41 @@ +using Microsoft.CodeAnalysis; +using System; +using System.Collections.Immutable; +using System.Linq; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + readonly struct MethodSignature + : IEquatable + { + public MethodSignature(string name, string receiverType, params string[] parameters) + => (Name, ReceiverType, Parameters) = (name, receiverType, ImmutableArray.Create(parameters)); + + string Name { get; } + string ReceiverType { get; } + ImmutableArray Parameters { get; } + + public bool Equals(MethodSignature other) + => Name == other.Name && ReceiverType == other.ReceiverType && Parameters.SequenceEqual(other.Parameters); + + public override bool Equals(object other) + => other is MethodSignature signature && Equals(signature); + + public override int GetHashCode() + { + unchecked + { + const int hashingBase = (int)2166136261; + const int hashingMultiplier = 16777619; + + var hash = hashingBase; + hash = (hash * hashingMultiplier) ^ Name.GetHashCode(); + hash = (hash * hashingMultiplier) ^ ReceiverType.GetHashCode(); + // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator + foreach(var parameter in Parameters) + hash = (hash * hashingMultiplier) ^ parameter.GetHashCode(); + return hash; + } + } + } +} diff --git a/NetFabric.Hyperlinq/NetFabric.Hyperlinq.csproj b/NetFabric.Hyperlinq/NetFabric.Hyperlinq.csproj index e7fceb2e2..ff22ce1c4 100644 --- a/NetFabric.Hyperlinq/NetFabric.Hyperlinq.csproj +++ b/NetFabric.Hyperlinq/NetFabric.Hyperlinq.csproj @@ -1,53 +1,55 @@  - net461;netstandard2.0;netcoreapp3.1;net5.0 - NetFabric.Hyperlinq - NetFabric.Hyperlinq - High performance LINQ implementation with minimal heap allocations. Supports enumerables, async enumerables, arrays, Memory and Span. - 3.0.0-beta40 + netstandard2.0 + NetFabric.Hyperlinq.SourceGenerator + NetFabric.Hyperlinq.SourceGenerator + High performance LINQ implementation with minimal heap allocations. Supports enumerables, async enumerables, Memory, and Span. + 3.0.0-beta48 Icon.png LICENSE netfabric, hyperlinq, linq, enumeration, extensions, performance true - enable - true - true - - - - - - $(NoWarn);8600;8601;8602;8603;8604 + true + false - - - - - + + + true + + + + true + - - + + - + - - - + + + + + - - - + + + + + + - + - - - + + all runtime; build; native; contentfiles; analyzers @@ -55,25 +57,29 @@ all runtime; build; native; contentfiles; analyzers - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + all runtime; build; native; contentfiles; analyzers - - - - True - True - Resource.resx - - - + ResXFileCodeGenerator Resource.Designer.cs + + + + True + True + Resources.resx + + diff --git a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.Memory.cs b/NetFabric.Hyperlinq/Partitioning/Skip/Skip.Memory.cs deleted file mode 100644 index 146ba14d7..000000000 --- a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.Memory.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Memory Skip(this Memory source, int count) - { - var (skipCount, takeCount) = Utils.Skip(source.Length, count); - return source.Slice(skipCount, takeCount); - } - } -} diff --git a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ReadOnlyMemory.cs deleted file mode 100644 index 1cd534108..000000000 --- a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ReadOnlyMemory.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ReadOnlyMemory Skip(this ReadOnlyMemory source, int count) - { - var (skipCount, takeCount) = Utils.Skip(source.Length, count); - return source.Slice(skipCount, takeCount); - } - } -} diff --git a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ReadOnlySpan.cs deleted file mode 100644 index 1666133d1..000000000 --- a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ReadOnlySpan.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan Skip(this ReadOnlySpan source, int count) - { - var (skipCount, takeCount) = Utils.Skip(source.Length, count); - return source.Slice(skipCount, takeCount); - } - } -} diff --git a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.Span.cs b/NetFabric.Hyperlinq/Partitioning/Skip/Skip.Span.cs deleted file mode 100644 index b96eebf91..000000000 --- a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.Span.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span Skip(this Span source, int count) - { - var (skipCount, takeCount) = Utils.Skip(source.Length, count); - return source.Slice(skipCount, takeCount); - } - } -} diff --git a/NetFabric.Hyperlinq/Partitioning/Take/Take.Memory.cs b/NetFabric.Hyperlinq/Partitioning/Take/Take.Memory.cs deleted file mode 100644 index 9d8e0ad63..000000000 --- a/NetFabric.Hyperlinq/Partitioning/Take/Take.Memory.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Memory Take(this Memory source, int count) - => source.Slice(0, Utils.Take(source.Length, count)); - } -} diff --git a/NetFabric.Hyperlinq/Partitioning/Take/Take.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Partitioning/Take/Take.ReadOnlyMemory.cs deleted file mode 100644 index d4249db87..000000000 --- a/NetFabric.Hyperlinq/Partitioning/Take/Take.ReadOnlyMemory.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ReadOnlyMemory Take(this ReadOnlyMemory source, int count) - => source.Slice(0, Utils.Take(source.Length, count)); - } -} diff --git a/NetFabric.Hyperlinq/Partitioning/Take/Take.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Partitioning/Take/Take.ReadOnlySpan.cs deleted file mode 100644 index 75abffd9d..000000000 --- a/NetFabric.Hyperlinq/Partitioning/Take/Take.ReadOnlySpan.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan Take(this ReadOnlySpan source, int count) - => source.Slice(0, Utils.Take(source.Length, count)); - } -} diff --git a/NetFabric.Hyperlinq/Projection/Select/Select.ReadOnlyList.cs b/NetFabric.Hyperlinq/Projection/Select/Select.ReadOnlyList.cs deleted file mode 100644 index b60cee6a1..000000000 --- a/NetFabric.Hyperlinq/Projection/Select/Select.ReadOnlyList.cs +++ /dev/null @@ -1,318 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectEnumerable> Select(this TList source, Func selector) - where TList : struct, IReadOnlyList - => source.Select(selector, 0, source.Count); - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static SelectEnumerable> Select(this TList source, Func selector, int offset, int count) - where TList : struct, IReadOnlyList - => source.Select>(new FunctionWrapper(selector), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectEnumerable Select(this TList source, TSelector selector = default) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => source.Select(selector, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static SelectEnumerable Select(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => new(in source, selector, offset, count); - - [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public partial struct SelectEnumerable - : IValueReadOnlyList.DisposableEnumerator> - , IList - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - readonly int offset; - readonly TList source; - TSelector selector; - - internal SelectEnumerable(in TList source, TSelector selector, int offset, int count) - => (this.source, this.offset, Count, this.selector) = (source, offset, count, selector); - - public readonly int Count { get; } - - public TResult this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if (index < 0 || index >= Count) Throw.IndexOutOfRangeException(); - - return selector.Invoke(source[index + offset]); - } - } - TResult IReadOnlyList.this[int index] - => this[index]; - TResult IList.this[int index] - { - get => this[index]; - - [ExcludeFromCodeCoverage] - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() => - // ReSharper disable once HeapView.BoxingAllocation - new DisposableEnumerator(in this); - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(Span span) - { - if (span.Length < Count) - Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - - Copy(source, offset, span, Count, selector); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TResult[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - public bool Contains(TResult item) - => source.Contains(item, default, selector, offset, Count); - - public int IndexOf(TResult item) - => ReadOnlyListExtensions.IndexOf(source, item, selector, offset, Count); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TResult item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TResult item) - => Throw.NotSupportedException(); - - [ExcludeFromCodeCoverage] - void IList.Insert(int index, TResult item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - { - readonly TList source; - TSelector selector; - readonly int end; - int index; - - internal Enumerator(in SelectEnumerable enumerable) - { - source = enumerable.source; - selector = enumerable.selector; - index = enumerable.offset - 1; - end = index + enumerable.Count; - } - - public TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(source[index]); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index <= end; - } - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly TList source; - TSelector selector; - readonly int end; - int index; - - internal DisposableEnumerator(in SelectEnumerable enumerable) - { - source = enumerable.source; - selector = enumerable.selector; - index = enumerable.offset - 1; - end = index + enumerable.Count; - } - - public TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(source[index]); - } - TResult IEnumerator.Current - => selector.Invoke(source[index]); - object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(source[index])!; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index <= end; - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public readonly void Dispose() { } - } - - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectEnumerable Skip(int count) - { - var (skipCount, takeCount) = Utils.Skip(Count, count); - return new SelectEnumerable(source, selector, offset + skipCount, takeCount); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectEnumerable Take(int count) - => new(source, selector, offset, Utils.Take(Count, count)); - - #endregion - #region Aggregation - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => Count is not 0; - - #endregion - #region Filtering - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.Select>(new SelectorSelectorCombination(this.selector, selector), offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => SelectAt>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.SelectAt>(new SelectorSelectorAtCombination(this.selector, selector), offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector, offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector, offset, Count); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => source.ElementAt(index, selector, offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => source.First(selector, offset, Count); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => source.Single(selector, offset, Count); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => source.ToArray(selector, offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.ToArray(selector, offset, Count, pool); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.ToList(selector, offset, Count); - - #endregion - - public readonly bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this in SelectEnumerable source) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => source.Count; - } -} - diff --git a/NetFabric.Hyperlinq/Projection/Select/Select.Span.cs b/NetFabric.Hyperlinq/Projection/Select/Select.Span.cs deleted file mode 100644 index cf1dac97b..000000000 --- a/NetFabric.Hyperlinq/Projection/Select/Select.Span.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectEnumerable> Select(this Span source, Func selector) - => ((ReadOnlySpan)source).Select(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectEnumerable Select(this Span source, TSelector selector = default) - where TSelector : struct, IFunction - => ((ReadOnlySpan)source).Select(selector); - } -} - diff --git a/NetFabric.Hyperlinq/Projection/Select/Select.ValueEnumerable.cs b/NetFabric.Hyperlinq/Projection/Select/Select.ValueEnumerable.cs deleted file mode 100644 index c11aae42a..000000000 --- a/NetFabric.Hyperlinq/Projection/Select/Select.ValueEnumerable.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectEnumerable> Select(this TEnumerable source, Func selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source.Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectEnumerable Select(this TEnumerable source, TSelector selector = default) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => new(in source, selector); - - [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct SelectEnumerable - : IValueEnumerable.Enumerator> - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - readonly TEnumerable source; - readonly TSelector selector; - - internal SelectEnumerable(in TEnumerable source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly - TSelector selector; - - internal Enumerator(in SelectEnumerable enumerable) - { - enumerator = enumerable.source.GetEnumerator(); - selector = enumerable.selector; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(enumerator.Current); - } - readonly TResult IEnumerator.Current - => selector.Invoke(enumerator.Current)!; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(enumerator.Current)!; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => enumerator.MoveNext(); - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() - => enumerator.Dispose(); - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => source.Count(); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Any(); - - #endregion - #region Filtering - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.Select>(new SelectorSelectorCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => SelectAt>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.SelectAt>(new SelectorSelectorAtCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, SelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, SelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, SelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, SelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => source.ElementAt(index, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => source.First(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => source.Single(selector); - - #endregion - #region Conversion - - public TResult[] ToArray() - => source.ToArray(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.ToArray(selector, pool); - - public List ToList() - => source.ToList(selector); - - #endregion - } - } -} - diff --git a/NetFabric.Hyperlinq/Projection/Select/Select.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Projection/Select/Select.ValueReadOnlyCollection.cs deleted file mode 100644 index 25ae799af..000000000 --- a/NetFabric.Hyperlinq/Projection/Select/Select.ValueReadOnlyCollection.cs +++ /dev/null @@ -1,216 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueReadOnlyCollectionExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectEnumerable> Select(this TEnumerable source, Func selector) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => Select>(source, new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectEnumerable Select(this TEnumerable source, TSelector selector = default) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => new(in source, selector); - - [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public partial struct SelectEnumerable - : IValueReadOnlyCollection.Enumerator> - , ICollection - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - readonly TEnumerable source; - TSelector selector; - - internal SelectEnumerable(in TEnumerable source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - public readonly int Count - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(Span span) - { - if (span.Length < Count) - Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - - if (source.Count is not 0) - { - checked - { - using var enumerator = source.GetEnumerator(); - for (var index = 0; enumerator.MoveNext(); index++) - span[index] = selector.Invoke(enumerator.Current); - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TResult[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - public bool Contains(TResult item) - => ValueReadOnlyCollectionExtensions.Contains(source, item, default, selector); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TResult item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TResult item) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly - TSelector selector; - - internal Enumerator(in SelectEnumerable enumerable) - { - enumerator = enumerable.source.GetEnumerator(); - selector = enumerable.selector; - } - - public TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(enumerator.Current); - } - TResult IEnumerator.Current - => selector.Invoke(enumerator.Current); - object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(enumerator.Current); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => enumerator.MoveNext(); - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() - => enumerator.Dispose(); - } - - #region Aggregation - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Count is not 0; - - #endregion - #region Filtering - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.Select>(source, new SelectorSelectorCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => SelectAt>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.SelectAt>(source, new SelectorSelectorAtCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, SelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, SelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, SelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, SelectEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => ValueReadOnlyCollectionExtensions.ElementAt(source, index, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => ValueReadOnlyCollectionExtensions.First(source, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => ValueReadOnlyCollectionExtensions.Single(source, selector); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => ValueReadOnlyCollectionExtensions.ToArray(source, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => ValueReadOnlyCollectionExtensions.ToArray(source, selector, pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => ValueReadOnlyCollectionExtensions.ToList(source, selector); - - #endregion - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this in SelectEnumerable source) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => source.Count; - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ReadOnlyList.cs b/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ReadOnlyList.cs deleted file mode 100644 index f13f5aa58..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ReadOnlyList.cs +++ /dev/null @@ -1,337 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectAtEnumerable> Select(this TList source, Func selector) - where TList : struct, IReadOnlyList - => source.Select(selector, 0, source.Count); - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static SelectAtEnumerable> Select(this TList source, Func selector, int offset, int count) - where TList : struct, IReadOnlyList - => source.SelectAt>(new FunctionWrapper(selector), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectAtEnumerable SelectAt(this TList source, TSelector selector = default) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => source.SelectAt(selector, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static SelectAtEnumerable SelectAt(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => new(in source, selector, offset, count); - - [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public partial struct SelectAtEnumerable - : IValueReadOnlyList.DisposableEnumerator> - , IList - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - readonly int offset; - readonly TList source; - TSelector selector; - - internal SelectAtEnumerable(in TList source, TSelector selector, int offset, int count) - => (this.source, this.offset, Count, this.selector) = (source, offset, count, selector); - - public readonly int Count { get; } - - public TResult this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if (index < 0 || index >= Count) Throw.IndexOutOfRangeException(); - - return selector.Invoke(source[index + offset], index); - } - } - TResult IReadOnlyList.this[int index] - => this[index]; - TResult IList.this[int index] - { - get => this[index]; - - [ExcludeFromCodeCoverage] - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new (in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new (in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() => - // ReSharper disable once HeapView.BoxingAllocation - new DisposableEnumerator(in this); - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(Span span) - { - if (span.Length < Count) - Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - - var end = Count; - if (offset is 0) - { - for (var index = 0; index < end; index++) - { - var item = source[index]; - span[index] = selector.Invoke(item, index); - } - } - else - { - for (var index = 0; index < end; index++) - { - var item = source[index + offset]; - span[index] = selector.Invoke(item, index); - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TResult[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - public bool Contains(TResult item) - => source.ContainsAt(item, default, selector, offset, Count); - - public int IndexOf(TResult item) - => ReadOnlyListExtensions.IndexOfAt(source, item, selector, offset, Count); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TResult item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TResult item) - => Throw.NotSupportedException(); - - [ExcludeFromCodeCoverage] - void IList.Insert(int index, TResult item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - { - readonly TList source; - TSelector selector; - readonly int offset; - readonly int end; - int index; - - internal Enumerator(in SelectAtEnumerable enumerable) - { - source = enumerable.source; - selector = enumerable.selector; - offset = enumerable.offset; - index = -1; - end = index + enumerable.Count; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(source[index + offset], index); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index <= end; - } - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - readonly TList source; - TSelector selector; - readonly int offset; - readonly int end; - int index; - - internal DisposableEnumerator(in SelectAtEnumerable enumerable) - { - source = enumerable.source; - selector = enumerable.selector; - offset = enumerable.offset; - index = -1; - end = index + enumerable.Count; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(source[index + offset], index); - } - readonly TResult IEnumerator.Current - => selector.Invoke(source[index + offset], index); - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(source[index + offset], index); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index <= end; - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public readonly void Dispose() { } - } - - - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable Skip(int count) - { - var (skipCount, takeCount) = Utils.Skip(Count, count); - return new SelectAtEnumerable(source, selector, offset + skipCount, takeCount); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable Take(int count) - => new(source, selector, offset, Utils.Take(Count, count)); - - #endregion - #region Aggregation - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => Count is not 0; - - #endregion - #region Filtering - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.SelectAt>(new SelectorAtSelectorCombination(this.selector, selector), offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => SelectAt>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.SelectAt>(new SelectorAtSelectorAtCombination(this.selector, selector), offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector, offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector, offset, Count); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => source.ElementAtAt(index, selector, offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => source.FirstAt(selector, offset, Count); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => source.SingleAt(selector, offset, Count); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => source.ToArrayAt(selector, offset, Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.ToArrayAt(selector, offset, Count, pool); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => source.ToListAt(selector, offset, Count); - - #endregion - - public readonly bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this in SelectAtEnumerable source) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - => source.Count; - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.Span.cs b/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.Span.cs deleted file mode 100644 index d4b073363..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.Span.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectAtEnumerable> Select(this Span source, Func selector) - => source.SelectAt>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectAtEnumerable SelectAt(this Span source, TSelector selector = default) - where TSelector : struct, IFunction - => ((ReadOnlySpan)source).SelectAt(selector); - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ValueEnumerable.cs b/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ValueEnumerable.cs deleted file mode 100644 index f2ad9684f..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ValueEnumerable.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectAtEnumerable> Select(this TEnumerable source, Func selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => source.SelectAt>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectAtEnumerable SelectAt(this TEnumerable source, TSelector selector = default) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => new(in source, selector); - - [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct SelectAtEnumerable - : IValueEnumerable.Enumerator> - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - readonly TEnumerable source; - readonly TSelector selector; - - internal SelectAtEnumerable(in TEnumerable source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly - TSelector selector; - int index; - - internal Enumerator(in SelectAtEnumerable enumerable) - { - enumerator = enumerable.source.GetEnumerator(); - selector = enumerable.selector; - index = -1; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(enumerator.Current, index); - } - readonly TResult IEnumerator.Current - => selector.Invoke(enumerator.Current, index); - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(enumerator.Current, index); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - if (enumerator.MoveNext()) - { - checked { index++; } - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() - => enumerator.Dispose(); - } - - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => source.Count(); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Any(); - - #endregion - #region Filtering - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.SelectAt>(new SelectorAtSelectorCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => SelectAt>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => source.SelectAt>(new SelectorAtSelectorAtCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, SelectAtEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, SelectAtEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, SelectAtEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, SelectAtEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => source.ElementAtAt(index, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => source.FirstAt(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => source.SingleAt(selector); - - #endregion - #region Conversion - - public TResult[] ToArray() - => source.ToArrayAt(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.ToArrayAt(selector, pool); - - public List ToList() - => source.ToListAt(selector); - - #endregion - } - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ValueReadOnlyCollection.cs deleted file mode 100644 index 33b2e1c63..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectAt/SelectAt.ValueReadOnlyCollection.cs +++ /dev/null @@ -1,225 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueReadOnlyCollectionExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectAtEnumerable> Select(this TEnumerable source, Func selector) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => SelectAt>(source, new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectAtEnumerable SelectAt(this TEnumerable source, TSelector selector = default) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => new(in source, selector); - - [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public partial struct SelectAtEnumerable - : IValueReadOnlyCollection.Enumerator> - , ICollection - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - readonly TEnumerable source; - TSelector selector; - - internal SelectAtEnumerable(in TEnumerable source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - public readonly int Count - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(Span span) - { - if (span.Length < Count) - Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - - if (source.Count is not 0) - { - checked - { - using var enumerator = source.GetEnumerator(); - for (var index = 0; enumerator.MoveNext(); index++) - span[index] = selector.Invoke(enumerator.Current, index)!; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CopyTo(TResult[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - public bool Contains(TResult item) - => ContainsAt(source, item, default, selector); - - [ExcludeFromCodeCoverage] - void ICollection.Add(TResult item) - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - void ICollection.Clear() - => Throw.NotSupportedException(); - [ExcludeFromCodeCoverage] - bool ICollection.Remove(TResult item) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly - TSelector selector; - int index; - - internal Enumerator(in SelectAtEnumerable enumerable) - { - enumerator = enumerable.source.GetEnumerator(); - selector = enumerable.selector; - index = -1; - } - - public TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(enumerator.Current, index); - } - TResult IEnumerator.Current - => selector.Invoke(enumerator.Current, index); - object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(enumerator.Current, index); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - if (enumerator.MoveNext()) - { - checked { index++; } - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() - => enumerator.Dispose(); - } - - #region Aggregation - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Count is not 0; - - #endregion - #region Filtering - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => Select>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.SelectAt>(source, new SelectorAtSelectorCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - => SelectAt>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SelectAtEnumerable> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueReadOnlyCollectionExtensions.SelectAt>(source, new SelectorAtSelectorAtCombination(this.selector, selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, SelectAtEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => this.SelectMany, SelectAtEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectManyEnumerable, SelectAtEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector2 : struct, IFunction - => this.SelectMany, SelectAtEnumerable.Enumerator, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => ElementAtAt(source, index, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => FirstAt(source, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => SingleAt(source, selector); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => ToArrayAt(source, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => ToArrayAt(source, selector, pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => ToListAt(source, selector); - - #endregion - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this in SelectAtEnumerable source) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => source.Count; - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectAtRef/SelectAtRef.ArraySegment.cs b/NetFabric.Hyperlinq/Projection/SelectAtRef/SelectAtRef.ArraySegment.cs deleted file mode 100644 index 21389167f..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectAtRef/SelectAtRef.ArraySegment.cs +++ /dev/null @@ -1,291 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectAtRefEnumerable> Select(this in ArraySegment source, FunctionIn selector) - => source.SelectAtRef>(new FunctionInWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectAtRefEnumerable SelectAtRef(this in ArraySegment source, TSelector selector = default) - where TSelector : struct, IFunctionIn - => new(in source, selector); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public partial struct ArraySegmentSelectAtRefEnumerable - : IValueReadOnlyList.Enumerator> - , IList - where TSelector : struct, IFunctionIn - { - internal readonly ArraySegment source; - internal TSelector selector; - - internal ArraySegmentSelectAtRefEnumerable(in ArraySegment source, TSelector selector) - { - this.source = source; - this.selector = selector; - } - - public readonly int Count - => source.Count; - - public TResult this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if (index < 0 || index >= source.Count) Throw.IndexOutOfRangeException(); - - return selector.Invoke(in source.Array![index + source.Offset], index); - } - } - TResult IReadOnlyList.this[int index] - => this[index]!; - TResult IList.this[int index] - { - get => this[index]; - - [ExcludeFromCodeCoverage] - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SelectAtRefEnumerator GetEnumerator() - => new(source.AsSpan(), selector); - readonly Enumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - - bool ICollection.IsReadOnly - => true; - - void ICollection.CopyTo(TResult[] array, int arrayIndex) - => CopyAtRef(source.AsSpan(), array.AsSpan(arrayIndex), selector); - void ICollection.Add(TResult item) - => Throw.NotSupportedException(); - void ICollection.Clear() - => Throw.NotSupportedException(); - public bool Contains(TResult item) - => ((ReadOnlySpan)source.AsSpan()).ContainsAtRef(item, default, selector); - bool ICollection.Remove(TResult item) - => Throw.NotSupportedException(); - int IList.IndexOf(TResult item) - => ArrayExtensions.IndexOfAtRef(source, item, selector); - void IList.Insert(int index, TResult item) - => Throw.NotSupportedException(); - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - readonly TSource[]? source; - TSelector selector; - readonly int offset; - readonly int end; - int index; - - internal Enumerator(in ArraySegmentSelectAtRefEnumerable enumerable) - { - source = enumerable.source.Array; - selector = enumerable.selector; - offset = enumerable.source.Offset; - index = -1; - end = index + enumerable.source.Count; - } - - public readonly TResult Current - => selector.Invoke(in source![index + offset], index); - readonly TResult IEnumerator.Current - => selector.Invoke(in source![index + offset], index)!; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(in source![index + offset], index); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index <= end; - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() { } - } - - #region Aggregation - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Count is not 0; - - #endregion - #region Filtering - - #endregion - #region Projection - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentSelectAtRefEnumerable, TSource, TResult, TResult2>> Select(Func selector) - // => Select>(new FunctionWrapper(selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentSelectAtRefEnumerable> Select(TSelector2 selector = default) - // where TSelector2 : struct, IFunction - // => source.SelectAt>(new SelectorAtSelectorCombination(this.selector, selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentSelectAtRefEnumerable, TSource, TResult, TResult2>> Select(Func selector) - // => SelectAt>(new FunctionWrapper(selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentSelectAtRefEnumerable> SelectAt(TSelector2 selector = default) - // where TSelector2 : struct, IFunction - // => source.SelectAt>(new SelectorAtSelectorAtCombination(this.selector, selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // where TSelector2 : struct, IFunction - // => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - #endregion - #region Element - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option ElementAt(int index) - // => ((ReadOnlySpan)source.AsSpan()).ElementAtAtRef(index, selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option First() - // => ((ReadOnlySpan)source.AsSpan()).FirstAtRef(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option Single() - // => ((ReadOnlySpan)source.AsSpan()).SingleAtRef(selector); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => ((ReadOnlySpan)source.AsSpan()).ToArrayAtRef(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => ((ReadOnlySpan)source.AsSpan()).ToArrayAtRef(selector, pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => ((ReadOnlySpan)source.AsSpan()).ToListAtRef(selector); - - #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentSelectAtRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumAtRef(source.selector); - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectAtRef/SelectAtRefEnumerator.cs b/NetFabric.Hyperlinq/Projection/SelectAtRef/SelectAtRefEnumerator.cs deleted file mode 100644 index dbbaf61a9..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectAtRef/SelectAtRefEnumerator.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct SelectAtRefEnumerator - where TSelector : struct, IFunctionIn - { - readonly ReadOnlySpan source; - TSelector selector; - int index; - - internal SelectAtRefEnumerator(ReadOnlySpan source, TSelector selector) - { - this.source = source; - this.selector = selector; - index = -1; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(in source[index], index); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index < source.Length; - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ArraySegment.cs b/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ArraySegment.cs deleted file mode 100644 index b4e1d4f38..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ArraySegment.cs +++ /dev/null @@ -1,232 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectManyEnumerable> SelectMany(this in ArraySegment source, Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => source.SelectMany>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectManyEnumerable SelectMany(this in ArraySegment source, TSelector selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => new(source, selector); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct ArraySegmentSelectManyEnumerable - : IValueEnumerable.Enumerator> - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - readonly ArraySegment source; - readonly TSelector selector; - - internal ArraySegmentSelectManyEnumerable(in ArraySegment source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - readonly TSource[]? source; - TSelector selector; - readonly int end; - EnumeratorState state; - int sourceIndex; - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TSubEnumerator subEnumerator; // do not make readonly - - internal Enumerator(in ArraySegmentSelectManyEnumerable enumerable) - { - source = enumerable.source.Array; - selector = enumerable.selector; - state = enumerable.source.Count is 0 - ? EnumeratorState.Complete - : EnumeratorState.Enumerating; - sourceIndex = enumerable.source.Offset - 1; - end = sourceIndex + enumerable.source.Count; - subEnumerator = default; - } - - public readonly TResult Current - => subEnumerator.Current; - readonly TResult IEnumerator.Current - => subEnumerator.Current; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => subEnumerator.Current; - - public bool MoveNext() - { - switch (state) - { - case EnumeratorState.Enumerating: - if (++sourceIndex >= end) - { - state = EnumeratorState.Complete; - return false; - } - - var enumerable = selector.Invoke(source![sourceIndex]); - subEnumerator = enumerable.GetEnumerator(); - - state = EnumeratorState.EnumeratingSub; - goto case EnumeratorState.EnumeratingSub; - - case EnumeratorState.EnumeratingSub: - if (!subEnumerator.MoveNext()) - { - state = EnumeratorState.Enumerating; - goto case EnumeratorState.Enumerating; - } - return true; - - case EnumeratorState.Complete: - default: - return false; - } - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() - => subEnumerator.Dispose(); - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() - => this.Count, Enumerator, TResult>(); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => this.Any, Enumerator, TResult>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => this.Any, Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate predicate = default) - where TPredicate : struct, IFunction - => this.Any, Enumerator, TResult, TPredicate>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => this.Any, Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate predicate = default) - where TPredicate : struct, IFunction - => this.AnyAt, Enumerator, TResult, TPredicate>(predicate); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate> WhereAt(TPredicate predicate = default) - where TPredicate : struct, IFunction - => ValueEnumerableExtensions.WhereAt, Enumerator, TResult, TPredicate>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, FunctionWrapper> Where(System.Func predicate) - => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate> Where(TPredicate predicate = default) - where TPredicate : struct, IFunction - => ValueEnumerableExtensions.Where, Enumerator, TResult, TPredicate>(this, predicate); - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) - => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, TSelector2> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2, TSelector2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) - => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, TSelector2> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueEnumerableExtensions.SelectAt, Enumerator, TResult, TResult2, TSelector2>(this, selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => this.ElementAt, Enumerator, TResult>(index); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => this.First, Enumerator, TResult>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => this.Single, Enumerator, TResult>(); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.AsyncValueEnumerableWrapper, Enumerator, TResult> AsAsyncValueEnumerable() - => ValueEnumerableExtensions.AsAsyncValueEnumerable, Enumerator, TResult>(this); - - #endregion - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SkipEnumerable, Enumerator, TResult> Skip(int count) - => ValueEnumerableExtensions.Skip, Enumerator, TResult>(this, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.TakeEnumerable, Enumerator, TResult> Take(int count) - => ValueEnumerableExtensions.Take, Enumerator, TResult>(this, count); - - #endregion - } - - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ReadOnlyList.cs b/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ReadOnlyList.cs deleted file mode 100644 index e072cddd1..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ReadOnlyList.cs +++ /dev/null @@ -1,250 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectManyEnumerable> SelectMany(this TList source, Func selector) - where TList : struct, IReadOnlyList - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => source.SelectMany(selector, 0, source.Count); - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static SelectManyEnumerable> SelectMany(this TList source, Func selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => source.SelectMany>(new FunctionWrapper(selector), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectManyEnumerable SelectMany(this TList source, TSelector selector) - where TList : struct, IReadOnlyList - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => source.SelectMany(selector, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static SelectManyEnumerable SelectMany(this TList source, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => new(source, selector, offset, count); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct SelectManyEnumerable - : IValueEnumerable.Enumerator> - where TList : struct, IReadOnlyList - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - readonly TList source; - readonly TSelector selector; - readonly int offset; - readonly int count; - - internal SelectManyEnumerable(TList source, TSelector selector, int offset, int count) - => (this.source, this.selector, this.offset, this.count) = (source, selector, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - readonly TList source; - TSelector selector; - readonly int end; - EnumeratorState state; - int sourceIndex; - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TSubEnumerator subEnumerator; // do not make readonly - - internal Enumerator(in SelectManyEnumerable enumerable) - { - source = enumerable.source; - selector = enumerable.selector; - state = EnumeratorState.Enumerating; - sourceIndex = enumerable.offset; - end = sourceIndex + enumerable.count; - subEnumerator = default; - } - - public readonly TResult Current - => subEnumerator.Current; - readonly TResult IEnumerator.Current - => subEnumerator.Current; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => subEnumerator.Current; - - public bool MoveNext() - { - switch (state) - { - case EnumeratorState.Enumerating: - if (++sourceIndex >= end) - { - state = EnumeratorState.Complete; - return false; - } - - var enumerable = selector.Invoke(source[sourceIndex]); - subEnumerator = enumerable.GetEnumerator(); - - state = EnumeratorState.EnumeratingSub; - goto case EnumeratorState.EnumeratingSub; - - case EnumeratorState.EnumeratingSub: - if (!subEnumerator.MoveNext()) - { - state = EnumeratorState.Enumerating; - goto case EnumeratorState.Enumerating; - } - return true; - - default: - return false; - } - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() => subEnumerator.Dispose(); - } - - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() - => this.Count, Enumerator, TResult>(); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => this.Any, Enumerator, TResult>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => this.Any, Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate predicate = default) - where TPredicate : struct, IFunction - => this.Any, Enumerator, TResult, TPredicate>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => this.Any, Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate predicate = default) - where TPredicate : struct, IFunction - => this.AnyAt, Enumerator, TResult, TPredicate>(predicate); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate> WhereAt(TPredicate predicate = default) - where TPredicate : struct, IFunction - => ValueEnumerableExtensions.WhereAt, Enumerator, TResult, TPredicate>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, FunctionWrapper> Where(System.Func predicate) - => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate> Where(TPredicate predicate = default) - where TPredicate : struct, IFunction - => ValueEnumerableExtensions.Where, Enumerator, TResult, TPredicate>(this, predicate); - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) - => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, TSelector2> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2, TSelector2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) - => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, TSelector2> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueEnumerableExtensions.SelectAt, Enumerator, TResult, TResult2, TSelector2>(this, selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => this.ElementAt, Enumerator, TResult>(index); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => this.First, Enumerator, TResult>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => this.Single, Enumerator, TResult>(); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.AsyncValueEnumerableWrapper, Enumerator, TResult> AsAsyncValueEnumerable() - => ValueEnumerableExtensions.AsAsyncValueEnumerable, Enumerator, TResult>(this); - - #endregion - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SkipEnumerable, Enumerator, TResult> Skip(int count) - => ValueEnumerableExtensions.Skip, Enumerator, TResult>(this, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.TakeEnumerable, Enumerator, TResult> Take(int count) - => ValueEnumerableExtensions.Take, Enumerator, TResult>(this, count); - - #endregion - } - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ReadOnlyMemory.cs deleted file mode 100644 index 0009dc360..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ReadOnlyMemory.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemorySelectManyEnumerable> SelectMany(this in ReadOnlyMemory source, Func selector) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => source.SelectMany>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemorySelectManyEnumerable SelectMany(this in ReadOnlyMemory source, TSelector selector = default) - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => new(source, selector); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct MemorySelectManyEnumerable - : IValueEnumerable.Enumerator> - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - readonly ReadOnlyMemory source; - readonly TSelector selector; - - internal MemorySelectManyEnumerable(ReadOnlyMemory source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - readonly ReadOnlyMemory source; - TSelector selector; - readonly int end; - EnumeratorState state; - int sourceIndex; - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TSubEnumerator subEnumerator; // do not make readonly - - internal Enumerator(in MemorySelectManyEnumerable enumerable) - { - source = enumerable.source; - selector = enumerable.selector; - state = EnumeratorState.Enumerating; - sourceIndex = -1; - end = sourceIndex + enumerable.source.Length; - subEnumerator = default; - } - - public readonly TResult Current - => subEnumerator.Current; - readonly TResult IEnumerator.Current - => subEnumerator.Current; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => subEnumerator.Current; - - public bool MoveNext() - { - switch (state) - { - case EnumeratorState.Enumerating: - if (++sourceIndex >= end) - { - state = EnumeratorState.Complete; - return false; - } - - var enumerable = selector.Invoke(source.Span[sourceIndex]); - subEnumerator = enumerable.GetEnumerator(); - - state = EnumeratorState.EnumeratingSub; - goto case EnumeratorState.EnumeratingSub; - - case EnumeratorState.EnumeratingSub: - if (!subEnumerator.MoveNext()) - { - state = EnumeratorState.Enumerating; - goto case EnumeratorState.Enumerating; - } - return true; - - default: - return false; - } - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => throw new NotSupportedException(); - - public void Dispose() - => subEnumerator.Dispose(); - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() - => this.Count, Enumerator, TResult>(); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => this.Any, Enumerator, TResult>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => this.Any, Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate predicate = default) - where TPredicate : struct, IFunction - => this.Any, Enumerator, TResult, TPredicate>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => this.Any, Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate predicate = default) - where TPredicate : struct, IFunction - => this.AnyAt, Enumerator, TResult, TPredicate>(predicate); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, Enumerator, TResult, TPredicate> WhereAt(TPredicate predicate = default) - where TPredicate : struct, IFunction - => ValueEnumerableExtensions.WhereAt, Enumerator, TResult, TPredicate>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, FunctionWrapper> Where(System.Func predicate) - => ValueEnumerableExtensions.Where, Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, Enumerator, TResult, TPredicate> Where(TPredicate predicate = default) - where TPredicate : struct, IFunction - => ValueEnumerableExtensions.Where, Enumerator, TResult, TPredicate>(this, predicate); - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) - => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectEnumerable, Enumerator, TResult, TResult2, TSelector2> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2, TSelector2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) - => ValueEnumerableExtensions.Select, Enumerator, TResult, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectAtEnumerable, Enumerator, TResult, TResult2, TSelector2> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueEnumerableExtensions.SelectAt, Enumerator, TResult, TResult2, TSelector2>(this, selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => this.ElementAt, Enumerator, TResult>(index); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => this.First, Enumerator, TResult>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => this.Single, Enumerator, TResult>(); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.AsyncValueEnumerableWrapper, Enumerator, TResult> AsAsyncValueEnumerable() - => ValueEnumerableExtensions.AsAsyncValueEnumerable, Enumerator, TResult>(this); - - #endregion - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SkipEnumerable, Enumerator, TResult> Skip(int count) - => ValueEnumerableExtensions.Skip, Enumerator, TResult>(this, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.TakeEnumerable, Enumerator, TResult> Take(int count) - => ValueEnumerableExtensions.Take, Enumerator, TResult>(this, count); - - #endregion - } - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ValueEnumerable.cs b/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ValueEnumerable.cs deleted file mode 100644 index d50200522..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectMany/SelectMany.ValueEnumerable.cs +++ /dev/null @@ -1,230 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - - [GeneratorMapping("TSelector", "NetFabric.Hyperlinq.FunctionWrapper")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectManyEnumerable> SelectMany(this TEnumerable source, Func selector) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - => source.SelectMany>(new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SelectManyEnumerable SelectMany(this TEnumerable source, TSelector selector = default) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - => new(source, selector); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public readonly partial struct SelectManyEnumerable - : IValueEnumerable.Enumerator> - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - where TSubEnumerable : IValueEnumerable - where TSubEnumerator : struct, IEnumerator - where TSelector : struct, IFunction - { - readonly TEnumerable source; - readonly TSelector selector; - - internal SelectManyEnumerable(in TEnumerable source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator sourceEnumerator; // do not make readonly - TSelector selector; - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TSubEnumerator subEnumerator; // do not make readonly - int state; - - internal Enumerator(in SelectManyEnumerable enumerable) - { - sourceEnumerator = enumerable.source.GetEnumerator(); - selector = enumerable.selector; - subEnumerator = default; - state = 0; - } - - public readonly TResult Current - => subEnumerator.Current; - readonly TResult IEnumerator.Current - => subEnumerator.Current; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => subEnumerator.Current!; - - public bool MoveNext() - { - switch (state) - { - case 0: - state = 1; - goto case 1; - - case 1: - if (!sourceEnumerator.MoveNext()) - break; - - var enumerable = selector.Invoke(sourceEnumerator.Current); - subEnumerator = enumerable.GetEnumerator(); - - state = 2; - goto case 2; - - case 2: - if (!subEnumerator.MoveNext()) - { - state = 1; - goto case 1; - } - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() => subEnumerator.Dispose(); - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() - => this.Count, SelectManyEnumerable.Enumerator, TResult>(); - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => this.Any, SelectManyEnumerable.Enumerator, TResult>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => this.Any, SelectManyEnumerable.Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(TPredicate predicate = default) - where TPredicate : struct, IFunction - => this.Any, SelectManyEnumerable.Enumerator, TResult, TPredicate>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any(Func predicate) - => this.Any, SelectManyEnumerable.Enumerator, TResult>(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool AnyAt(TPredicate predicate = default) - where TPredicate : struct, IFunction - => this.AnyAt, SelectManyEnumerable.Enumerator, TResult, TPredicate>(predicate); - - #endregion - #region Filtering - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, SelectManyEnumerable.Enumerator, TResult, FunctionWrapper> Where(Func predicate) - => ValueEnumerableExtensions.Where, SelectManyEnumerable.Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereAtEnumerable, SelectManyEnumerable.Enumerator, TResult, TPredicate> WhereAt(TPredicate predicate = default) - where TPredicate : struct, IFunction - => ValueEnumerableExtensions.WhereAt, SelectManyEnumerable.Enumerator, TResult, TPredicate>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, SelectManyEnumerable.Enumerator, TResult, FunctionWrapper> Where(System.Func predicate) - => ValueEnumerableExtensions.Where, SelectManyEnumerable.Enumerator, TResult>(this, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.WhereEnumerable, SelectManyEnumerable.Enumerator, TResult, TPredicate> Where(TPredicate predicate = default) - where TPredicate : struct, IFunction - => ValueEnumerableExtensions.Where, SelectManyEnumerable.Enumerator, TResult, TPredicate>(this, predicate); - - #endregion - #region Projection - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectEnumerable, SelectManyEnumerable.Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) - => ValueEnumerableExtensions.Select, SelectManyEnumerable.Enumerator, TResult, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectEnumerable, SelectManyEnumerable.Enumerator, TResult, TResult2, TSelector2> Select(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueEnumerableExtensions.Select, SelectManyEnumerable.Enumerator, TResult, TResult2, TSelector2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectAtEnumerable, SelectManyEnumerable.Enumerator, TResult, TResult2, FunctionWrapper> Select(Func selector) - => ValueEnumerableExtensions.Select, SelectManyEnumerable.Enumerator, TResult, TResult2>(this, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SelectAtEnumerable, SelectManyEnumerable.Enumerator, TResult, TResult2, TSelector2> SelectAt(TSelector2 selector = default) - where TSelector2 : struct, IFunction - => ValueEnumerableExtensions.SelectAt, SelectManyEnumerable.Enumerator, TResult, TResult2, TSelector2>(this, selector); - - #endregion - #region Element - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option ElementAt(int index) - => this.ElementAt, SelectManyEnumerable.Enumerator, TResult>(index); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option First() - => this.First, SelectManyEnumerable.Enumerator, TResult>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Option Single() - => this.Single, SelectManyEnumerable.Enumerator, TResult>(); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.AsyncValueEnumerableWrapper, SelectManyEnumerable.Enumerator, TResult> AsAsyncValueEnumerable() - => ValueEnumerableExtensions.AsAsyncValueEnumerable, SelectManyEnumerable.Enumerator, TResult>(this); - - #endregion - #region Partitioning - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.SkipEnumerable, SelectManyEnumerable.Enumerator, TResult> Skip(int count) - => ValueEnumerableExtensions.Skip, SelectManyEnumerable.Enumerator, TResult>(this, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueEnumerableExtensions.TakeEnumerable, SelectManyEnumerable.Enumerator, TResult> Take(int count) - => ValueEnumerableExtensions.Take, SelectManyEnumerable.Enumerator, TResult>(this, count); - - #endregion - } - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectRef/SelectRef.ArraySegment.cs b/NetFabric.Hyperlinq/Projection/SelectRef/SelectRef.ArraySegment.cs deleted file mode 100644 index 0adce42b4..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectRef/SelectRef.ArraySegment.cs +++ /dev/null @@ -1,268 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectRefEnumerable> Select(this in ArraySegment source, FunctionIn selector) - => source.SelectRef>(new FunctionInWrapper(selector)); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ArraySegmentSelectRefEnumerable SelectRef(this in ArraySegment source, TSelector selector = default) - where TSelector : struct, IFunctionIn - => new(in source, selector); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public partial struct ArraySegmentSelectRefEnumerable - : IValueReadOnlyList.Enumerator> - , IList - where TSelector : struct, IFunctionIn - { - internal readonly ArraySegment source; - internal TSelector selector; - - internal ArraySegmentSelectRefEnumerable(in ArraySegment source, TSelector selector) - => (this.source, this.selector) = (source, selector); - - public readonly int Count - => source.Count; - - public TResult this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if (index < 0 || index >= source.Count) Throw.IndexOutOfRangeException(); - - return selector.Invoke(in source.Array![index + source.Offset]); - } - } - TResult IReadOnlyList.this[int index] - => this[index]; - TResult IList.this[int index] - { - get => this[index]; - - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - public readonly SelectRefEnumerator GetEnumerator() - => new (source.AsSpan(), selector); - readonly Enumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - - bool ICollection.IsReadOnly - => true; - - void ICollection.CopyTo(TResult[] array, int arrayIndex) - => CopyRef(source.AsSpan(), array.AsSpan(arrayIndex), selector); - void ICollection.Add(TResult item) - => Throw.NotSupportedException(); - void ICollection.Clear() - => Throw.NotSupportedException(); - public bool Contains(TResult item) - => ((ReadOnlySpan)source.AsSpan()).ContainsRef(item, default, selector); - bool ICollection.Remove(TResult item) - => Throw.NotSupportedException(); - int IList.IndexOf(TResult item) - => ArrayExtensions.IndexOfRef(source, item, selector); - void IList.Insert(int index, TResult item) - => Throw.NotSupportedException(); - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - readonly TSource[]? source; - TSelector selector; - readonly int end; - int index; - - internal Enumerator(in ArraySegmentSelectRefEnumerable enumerable) - { - source = enumerable.source.Array; - selector = enumerable.selector; - index = enumerable.source.Offset - 1; - end = index + enumerable.source.Count; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(in source![index]); - } - readonly TResult IEnumerator.Current - => selector.Invoke(in source![index]); - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(in source![index]); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index <= end; - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() { } - } - - #region Aggregation - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Count is not 0; - - #endregion - #region Filtering - - #endregion - #region Projection - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentSelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - // => Select>(new FunctionWrapper(selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentSelectEnumerable> Select(TSelector2 selector = default) - // where TSelector2 : struct, IFunction - // => ((ReadOnlySpan)source.AsSpan()).SelectRef>(new SelectorSelectorCombination(this.selector, selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentSelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - // => SelectAt>(new FunctionWrapper(selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ArraySegmentSelectAtEnumerable> SelectAt(TSelector2 selector = default) - // where TSelector2 : struct, IFunction - // => ((ReadOnlySpan)source.AsSpan()).SelectAtRef>(new SelectorSelectorAtCombination(this.selector, selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // => this.SelectManyRef, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // where TSelector2 : struct, IFunction - // => this.SelectManyRef, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - #endregion - #region Element - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option ElementAt(int index) - // => ((ReadOnlySpan)source.AsSpan()).ElementAtRef(index, selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option First() - // => ((ReadOnlySpan)source.AsSpan()).FirstRef(selector); - - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option Single() - // => ((ReadOnlySpan)source.AsSpan()).SingleRef(selector); - - #endregion - #region Conversion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TResult[] ToArray() - => ((ReadOnlySpan)source.AsSpan()).ToArrayRef(selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => ((ReadOnlySpan)source.AsSpan()).ToArrayRef(selector, pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ToList() - => ((ReadOnlySpan)source.AsSpan()).ToListRef(selector); - - #endregion - - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ArraySegmentSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => ((ReadOnlySpan)source.source.AsSpan()).SumRef(source.selector); - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectRef/SelectRef.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Projection/SelectRef/SelectRef.ReadOnlyMemory.cs deleted file mode 100644 index 8aa551a3a..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectRef/SelectRef.ReadOnlyMemory.cs +++ /dev/null @@ -1,284 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemorySelectRefEnumerable> Select(this ReadOnlyMemory source, FunctionIn selector) - => source.SelectRef>(new FunctionInWrapper(selector)); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static MemorySelectRefEnumerable SelectRef(this ReadOnlyMemory source, TSelector selector = default) - where TSelector : struct, IFunctionIn - => new(source, selector); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public partial struct MemorySelectRefEnumerable - : IValueReadOnlyList.Enumerator> - , IList - where TSelector : struct, IFunctionIn - { - internal readonly ReadOnlyMemory source; - internal TSelector selector; - - internal MemorySelectRefEnumerable(ReadOnlyMemory source, TSelector selector) - { - this.source = source; - this.selector = selector; - } - - public readonly int Count - => source.Length; - - public TResult this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(in source.Span[index]); - } - TResult IReadOnlyList.this[int index] - => selector.Invoke(in source.Span[index]); - TResult IList.this[int index] - { - get => selector.Invoke(in source.Span[index]); - - [ExcludeFromCodeCoverage] - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - public readonly SelectRefEnumerator GetEnumerator() - => new(source.Span, selector); - readonly Enumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - - bool ICollection.IsReadOnly - => true; - - void ICollection.CopyTo(TResult[] array, int arrayIndex) - => ArrayExtensions.CopyRef(source.Span, array.AsSpan(arrayIndex), selector); - void ICollection.Add(TResult item) - => Throw.NotSupportedException(); - void ICollection.Clear() - => Throw.NotSupportedException(); - public bool Contains(TResult item) - => source.Span.ContainsRef(item, default, selector); - bool ICollection.Remove(TResult item) - => Throw.NotSupportedException(); - int IList.IndexOf(TResult item) - => ArrayExtensions.IndexOfRef(source.Span, item, selector); - void IList.Insert(int index, TResult item) - => Throw.NotSupportedException(); - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - readonly ReadOnlyMemory source; - TSelector selector; - int index; - - internal Enumerator(in MemorySelectRefEnumerable enumerable) - { - source = enumerable.source; - selector = enumerable.selector; - index = -1; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(in source.Span[index]); - } - readonly TResult IEnumerator.Current - => selector.Invoke(in source.Span[index]); - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(in source.Span[index]); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index < source.Length; - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() { } - } - - //#region Aggregation - - //#endregion - //#region Quantifier - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool Any() - // => source.Length is not 0; - - //#endregion - //#region Filtering - - //#endregion - //#region Projection - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public MemorySelectRefEnumerable, TSource, TResult, TResult2>> Select(Func selector) - // => Select>(new FunctionWrapper(selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public MemorySelectRefEnumerable> Select(TSelector2 selector = default) - // where TSelector2 : struct, IFunction - // => source.Select>(new SelectorSelectorCombination(this.selector, selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public MemorySelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - // => SelectAt>(new FunctionWrapper(selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public MemorySelectAtEnumerable> SelectAt(TSelector2 selector = default) - // where TSelector2 : struct, IFunction - // => source.SelectAt>(new SelectorSelectorAtCombination(this.selector, selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, FunctionWrapper> SelectMany(Func selector) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2>(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public readonly ReadOnlyListExtensions.SelectManyEnumerable, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2> SelectMany(TSelector2 selector = default) - // where TSubEnumerable : IValueEnumerable - // where TSubEnumerator : struct, IEnumerator - // where TSelector2 : struct, IFunction - // => this.SelectMany, TResult, TSubEnumerable, TSubEnumerator, TResult2, TSelector2>(selector); - - //#endregion - //#region Element - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option ElementAt(int index) - // => source.Span.ElementAt(index, selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option First() - // => source.Span.First(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option Single() - // => source.Span.Single(selector); - - //#endregion - //#region Conversion - - //public TResult[] ToArray() - // => source.Span.ToArray(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public IMemoryOwner ToArray(MemoryPool pool) - // => source.Span.ToArray(selector, pool); - - //public List ToList() - // => source.Span.ToList(selector); - - //#endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this MemorySelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.Span.SumRef(source.selector); - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectRef/SelectRef.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Projection/SelectRef/SelectRef.ReadOnlySpan.cs deleted file mode 100644 index be17e77a2..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectRef/SelectRef.ReadOnlySpan.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectRefEnumerable> Select(this ReadOnlySpan source, FunctionIn selector) - => source.SelectRef>(new FunctionInWrapper(selector)); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectRefEnumerable SelectRef(this ReadOnlySpan source, TSelector selector = default) - where TSelector : struct, IFunctionIn - => new(source, selector); - - [GeneratorIgnore] - [StructLayout(LayoutKind.Auto)] - public ref struct SpanSelectRefEnumerable - where TSelector : struct, IFunctionIn - { - internal readonly ReadOnlySpan source; - internal TSelector selector; - - internal SpanSelectRefEnumerable(ReadOnlySpan source, TSelector selector) - { - this.source = source; - this.selector = selector; - } - - public readonly SelectRefEnumerator GetEnumerator() - => new(source, selector); - - public readonly int Count - => source.Length; - - public TResult this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(in source[index]); - } - - //#region Aggregation - - //#endregion - //#region Quantifier - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public bool Any() - // => source.Length is not 0; - - //#endregion - //#region Filtering - - //#endregion - //#region Projection - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public SpanSelectEnumerable, TSource, TResult, TResult2>> Select(Func selector) - // => Select>(new FunctionWrapper(selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public SpanSelectEnumerable> Select(TSelector2 selector = default) - // where TSelector2 : struct, IFunction - // => source.Select>(new SelectorSelectorCombination(this.selector, selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public SpanSelectAtEnumerable, TSource, TResult, TResult2>> Select(Func selector) - // => SelectAt>(new FunctionWrapper(selector)); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public SpanSelectAtEnumerable> SelectAt(TSelector2 selector = default) - // where TSelector2 : struct, IFunction - // => source.SelectAt>(new SelectorSelectorAtCombination(this.selector, selector)); - - //#endregion - //#region Element - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option ElementAt(int index) - // => source.ElementAt(index, selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option First() - // => source.First(selector); - - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public Option Single() - // => source.Single(selector); - - //#endregion - //#region Conversion - - //public TResult[] ToArray() - // => source.ToArray(selector); - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public IMemoryOwner ToArray(MemoryPool pool) - // => source.ToArray(selector, pool); - - //public List ToList() - // => source.ToList(selector); - - //#endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this SpanSelectRefEnumerable source) - where TSelector : struct, IFunctionIn - => source.source.SumRef(source.selector); - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectRef/SelectRefEnumerator.cs b/NetFabric.Hyperlinq/Projection/SelectRef/SelectRefEnumerator.cs deleted file mode 100644 index 5d4683a61..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectRef/SelectRefEnumerator.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - [StructLayout(LayoutKind.Auto)] - public ref struct SelectRefEnumerator - where TSelector : struct, IFunctionIn - { - readonly ReadOnlySpan source; - TSelector selector; - int index; - - internal SelectRefEnumerator(ReadOnlySpan source, TSelector selector) - { - this.source = source; - this.selector = selector; - index = -1; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(in source[index]); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++index < source.Length; - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.ArraySegment.cs b/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.ArraySegment.cs deleted file mode 100644 index 901da4d52..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.ArraySegment.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static MemorySelectVectorContext, Vector>, FunctionWrapper> SelectVector(this ArraySegment source, Func, Vector> vectorSelector, Func selector) - where TSource : struct - where TResult : struct - => source.AsMemory().SelectVector(vectorSelector, selector); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static MemorySelectVectorContext SelectVector(this ArraySegment source, TSelector selector = default) - where TSelector : struct, IFunction, Vector>, IFunction - where TSource : struct - where TResult : struct - => source.AsMemory().SelectVector(selector); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static MemorySelectVectorContext SelectVector(this ArraySegment source, TVectorSelector vectorSelector = default, TSelector selector = default) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - => source.AsMemory().SelectVector(vectorSelector, selector); - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.Memory.cs b/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.Memory.cs deleted file mode 100644 index afb428bd7..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.Memory.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static MemorySelectVectorContext, Vector>, FunctionWrapper> SelectVector(this Memory source, Func, Vector> vectorSelector, Func selector) - where TSource : struct - where TResult : struct - => ((ReadOnlyMemory)source).SelectVector(vectorSelector, selector); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static MemorySelectVectorContext SelectVector(this Memory source, TSelector selector = default) - where TSelector : struct, IFunction, Vector>, IFunction - where TSource : struct - where TResult : struct - => ((ReadOnlyMemory)source).SelectVector(selector); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static MemorySelectVectorContext SelectVector(this Memory source, TVectorSelector vectorSelector = default, TSelector selector = default) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - => ((ReadOnlyMemory)source).SelectVector(vectorSelector, selector); - - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.Range.cs b/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.Range.cs deleted file mode 100644 index feed02386..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.Range.cs +++ /dev/null @@ -1,357 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerable - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static RangeSelectVectorEnumerable, Vector>, FunctionWrapper> SelectVector(int start, int count, Func, Vector> vectorSelector, Func selector) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TResult : struct - => SelectVector, Vector>, FunctionWrapper>(start, count, new FunctionWrapper, Vector>(vectorSelector), new FunctionWrapper(selector)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static RangeSelectVectorEnumerable SelectVector(int start, int count, TSelector selector = default) - where TSelector : struct, IFunction, Vector>, IFunction - where TResult : struct - => SelectVector(start, count, selector, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static RangeSelectVectorEnumerable SelectVector(int start, int count, TVectorSelector vectorSelector = default, TSelector selector = default) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TResult : struct - => new(start, count, vectorSelector, selector); - - [GeneratorIgnore] - // [GeneratorMapping("TSource", "TResult")] - [StructLayout(LayoutKind.Auto)] - public partial struct RangeSelectVectorEnumerable - : IValueReadOnlyList.DisposableEnumerator> - , IList - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TResult : struct - { - internal readonly int start; - internal readonly int count; - internal TVectorSelector vectorSelector; - internal TSelector selector; - - internal RangeSelectVectorEnumerable(int start, int count, TVectorSelector vectorSelector, TSelector selector) - { - if (Vector.Count != Vector.Count) - Throw.NotSupportedException(); - - this.start = start; - this.count = count; - this.vectorSelector = vectorSelector; - this.selector = selector; - } - - public readonly int Count - => count; - - public TResult this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if (index < 0 || index >= count) Throw.IndexOutOfRangeException(); - - return selector.Invoke(start + index); - } - } - TResult IReadOnlyList.this[int index] - => this[index]; - TResult IList.this[int index] - { - get => this[index]; - - // ReSharper disable once ValueParameterNotUsed - set => Throw.NotSupportedException(); - } - - public readonly Enumerator GetEnumerator() - => new (in this); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new DisposableEnumerator(in this); - - - bool ICollection.IsReadOnly - => true; - - public void CopyTo(Span span) - { - if (span.Length < count) - Throw.ArgumentException(Resource.DestinationNotLongEnough, nameof(span)); - - ArrayExtensions.CopyRange(start, count, span, vectorSelector, selector); - } - - void ICollection.CopyTo(TResult[] array, int arrayIndex) - => CopyTo(array.AsSpan().Slice(arrayIndex)); - - void ICollection.Add(TResult item) - => Throw.NotSupportedException(); - void ICollection.Clear() - => Throw.NotSupportedException(); - - public unsafe bool Contains(TResult item) - { - if (count is 0) - return false; - - var index = 0; - - if (Vector.IsHardwareAccelerated && count > Vector.Count * 2) - { - var seed = stackalloc int[Vector.Count]; - if (start is 0) - { - for (var seedIndex = 0; seedIndex < Vector.Count; seedIndex++) - seed[seedIndex] = seedIndex; - } - else - { - for (var seedIndex = 0; seedIndex < Vector.Count; seedIndex++) - seed[seedIndex] = seedIndex + start; - } - - var vector = Unsafe.AsRef>(seed); - var vectorItem = new Vector(item); - if (Vector.EqualsAny(vectorSelector.Invoke(vector), vectorItem)) - return true; - - var vectorIncrement = new Vector(Vector.Count); - vector += vectorIncrement; - for (index = 0; index < count - Vector.Count; index += Vector.Count) - { - if (Vector.EqualsAny(vectorSelector.Invoke(vector), vectorItem)) - return true; - - vector += vectorIncrement; - } - } - - var end = start + count; - for (var value = index + start; value < end; value++) - { - if (GenericsOperator.Equals(selector.Invoke(value), item)) - return true; - } - - return false; - } - - bool ICollection.Remove(TResult item) - => Throw.NotSupportedException(); - int IList.IndexOf(TResult item) - { - var end = start + count; - for (var value = start; value < end; value++) - { - if (EqualityComparer.Default.Equals(selector.Invoke(value), item)) - return value - start; - } - return -1; - } - - void IList.Insert(int index, TResult item) - => Throw.NotSupportedException(); - void IList.RemoveAt(int index) - => Throw.NotSupportedException(); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - { - TSelector selector; - readonly int end; - int value; - - internal Enumerator(in RangeSelectVectorEnumerable enumerable) - { - selector = enumerable.selector; - value = enumerable.start - 1; - end = value + enumerable.count; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++value <= end; - } - - [StructLayout(LayoutKind.Auto)] - public struct DisposableEnumerator - : IEnumerator - { - TSelector selector; - readonly int end; - int value; - - internal DisposableEnumerator(in RangeSelectVectorEnumerable enumerable) - { - selector = enumerable.selector; - value = enumerable.start - 1; - end = value + enumerable.count; - } - - public readonly TResult Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => selector.Invoke(value); - } - readonly TResult IEnumerator.Current - => selector.Invoke(value); - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => selector.Invoke(value); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - => ++value <= end; - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() { } - } - - #region Aggregation - - #endregion - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => count is not 0; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TResult value, IEqualityComparer? comparer) - => comparer switch - { - null => Contains(value), - _ => ReadOnlyListExtensions.Contains(this, value, comparer) - }; - - #endregion - #region Filtering - - #endregion - #region Projection - - #endregion - #region Element - - #endregion - #region Conversion - - public TResult[] ToArray() - { - var result = Utils.AllocateUninitializedArray(count); - ArrayExtensions.CopyRange(start, count, result.AsSpan(), vectorSelector, selector); - return result; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - { - var result = pool.RentSliced(count); - ArrayExtensions.CopyRange(start, count, result.Memory.Span, vectorSelector, selector); - return result; - } - - public List ToList() - => count switch - { - 0 => new List(), - _ => ToArray().AsList() - }; - - #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = null) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current!, otherEnumerator.Current)) - return false; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this RangeSelectVectorEnumerable source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TResult : struct - => source.Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this RangeSelectVectorEnumerable source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - => SumRange(source.start, source.count, source.vectorSelector, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this RangeSelectVectorEnumerable source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - => SumRange(source.start, source.count, source.vectorSelector, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this RangeSelectVectorEnumerable source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - => SumRange(source.start, source.count, source.vectorSelector, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this RangeSelectVectorEnumerable source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - => SumRange(source.start, source.count, source.vectorSelector, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this RangeSelectVectorEnumerable source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - => SumRange(source.start, source.count, source.vectorSelector, source.selector); - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.ReadOnlyMemory.cs deleted file mode 100644 index 704276e88..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.ReadOnlyMemory.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static MemorySelectVectorContext, Vector>, FunctionWrapper> SelectVector(this ReadOnlyMemory source, Func, Vector> vectorSelector, Func selector) - where TSource : struct - where TResult : struct - => source.SelectVector, Vector>, FunctionWrapper>(new FunctionWrapper, Vector>(vectorSelector), new FunctionWrapper(selector)); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static MemorySelectVectorContext SelectVector(this ReadOnlyMemory source, TSelector selector = default) - where TSelector : struct, IFunction, Vector>, IFunction - where TSource : struct - where TResult : struct - => source.SelectVector(selector, selector); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static MemorySelectVectorContext SelectVector(this ReadOnlyMemory source, TVectorSelector vectorSelector = default, TSelector selector = default) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - => new(source, vectorSelector, selector); - - [StructLayout(LayoutKind.Auto)] - public struct MemorySelectVectorContext - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - { - internal readonly ReadOnlyMemory source; - internal TVectorSelector vectorSelector; - internal TSelector selector; - - internal MemorySelectVectorContext(ReadOnlyMemory source, TVectorSelector vectorSelector, TSelector selector) - { - if (Vector.Count != Vector.Count) - Throw.NotSupportedException(); - - this.source = source; - this.vectorSelector = vectorSelector; - this.selector = selector; - } - - #region Aggregation - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Count() - => source.Length; - - #endregion - - #region Quantifier - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Any() - => source.Length is not 0; - - #endregion - #region Filtering - - #endregion - #region Projection - - #endregion - #region Element - - #endregion - #region Conversion - - public TResult[] ToArray() - => source.Span.ToArrayVector(vectorSelector, selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IMemoryOwner ToArray(MemoryPool pool) - => source.Span.ToArrayVector(vectorSelector, selector, pool); - - public List ToList() - => source.Span.ToListVector(vectorSelector, selector); - - #endregion - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this MemorySelectVectorContext source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - => source.source.Span.Sum(source.vectorSelector, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this MemorySelectVectorContext source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - => source.source.Span.Sum(source.vectorSelector, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this MemorySelectVectorContext source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - => source.source.Span.Sum(source.vectorSelector, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this MemorySelectVectorContext source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - => source.source.Span.Sum(source.vectorSelector, source.selector); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this MemorySelectVectorContext source) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - => source.source.Span.Sum(source.vectorSelector, source.selector); - - } -} - diff --git a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.Span.cs b/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.Span.cs deleted file mode 100644 index ad91df53f..000000000 --- a/NetFabric.Hyperlinq/Projection/SelectVector/SelectVector.Span.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectVectorContext, Vector>, FunctionWrapper> SelectVector(this Span source, Func, Vector> vectorSelector, Func selector) - where TSource : struct - where TResult : struct - => ((ReadOnlySpan)source).SelectVector(vectorSelector, selector); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectVectorContext SelectVector(this Span source, TSelector selector = default) - where TSelector : struct, IFunction, Vector>, IFunction - where TSource : struct - where TResult : struct - => ((ReadOnlySpan)source).SelectVector(selector); - - [GeneratorIgnore] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanSelectVectorContext SelectVector(this Span source, TVectorSelector vectorSelector = default, TSelector selector = default) - where TVectorSelector : struct, IFunction, Vector> - where TSelector : struct, IFunction - where TSource : struct - where TResult : struct - => ((ReadOnlySpan)source).SelectVector(vectorSelector, selector); - - } -} - diff --git a/NetFabric.Hyperlinq/Properties/AssemblyInfo.cs b/NetFabric.Hyperlinq/Properties/AssemblyInfo.cs index 718964469..a48e711f2 100644 --- a/NetFabric.Hyperlinq/Properties/AssemblyInfo.cs +++ b/NetFabric.Hyperlinq/Properties/AssemblyInfo.cs @@ -1,3 +1,3 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; -[assembly:InternalsVisibleTo("NetFabric.Hyperlinq.UnitTests")] \ No newline at end of file +[assembly: InternalsVisibleTo("NetFabric.Hyperlinq.UnitTests")] \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Quantifier/All/All.ReadOnlyList.cs b/NetFabric.Hyperlinq/Quantifier/All/All.ReadOnlyList.cs deleted file mode 100644 index 60f7c4fc5..000000000 --- a/NetFabric.Hyperlinq/Quantifier/All/All.ReadOnlyList.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this TList source, Func predicate) - where TList : struct, IReadOnlyList - => source.All(predicate, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool All(this TList source, Func predicate, int offset, int count) - where TList : struct, IReadOnlyList - => source.All>(new FunctionWrapper(predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this TList source, TPredicate predicate) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source.All(predicate, 0, source.Count); - - static bool All(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (!predicate.Invoke(item)) - return false; - } - return true; - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this TList source, Func predicate) - where TList : struct, IReadOnlyList - => source.All(predicate, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool All(this TList source, Func predicate, int offset, int count) - where TList : struct, IReadOnlyList - => source.AllAt>(new FunctionWrapper(predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AllAt(this TList source, TPredicate predicate) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source.AllAt(predicate, 0, source.Count); - - static bool AllAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - if (offset is 0) - { - for (var index = 0; index < count; index++) - { - var item = source[index]; - if (!predicate.Invoke(item, index)) - return false; - } - } - else - { - for (var index = 0; index < count; index++) - { - var item = source[index + offset]; - if (!predicate.Invoke(item, index)) - return false; - } - } - return true; - } - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/All/All.Span.cs b/NetFabric.Hyperlinq/Quantifier/All/All.Span.cs deleted file mode 100644 index fd7633936..000000000 --- a/NetFabric.Hyperlinq/Quantifier/All/All.Span.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this Span source, Func predicate) - => source.All(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunction - => ((ReadOnlySpan)source).All(predicate); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this Span source, Func predicate) - => source.AllAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AllAt(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunction - => ((ReadOnlySpan)source).AllAt(predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/AllRef/AllRef.Memory.cs b/NetFabric.Hyperlinq/Quantifier/AllRef/AllRef.Memory.cs deleted file mode 100644 index 0b3f5828e..000000000 --- a/NetFabric.Hyperlinq/Quantifier/AllRef/AllRef.Memory.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this Memory source, FunctionIn predicate) - => source.AllRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AllRef(this Memory source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => source.Span.AllRef(predicate); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this Memory source, FunctionIn predicate) - => source.AllAtRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AllAtRef(this Memory source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => source.Span.AllAtRef(predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/AllRef/AllRef.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Quantifier/AllRef/AllRef.ReadOnlySpan.cs deleted file mode 100644 index 5de264e8c..000000000 --- a/NetFabric.Hyperlinq/Quantifier/AllRef/AllRef.ReadOnlySpan.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this ReadOnlySpan source, FunctionIn predicate) - => source.AllRef(new FunctionInWrapper(predicate)); - - public static bool AllRef(this ReadOnlySpan source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - { - foreach (ref readonly var item in source) - { - if (!predicate.Invoke(in item)) - return false; - } - - return true; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this ReadOnlySpan source, FunctionIn predicate) - => source.AllAtRef(new FunctionInWrapper(predicate)); - - public static bool AllAtRef(this ReadOnlySpan source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - { - for (var index = 0; index < source.Length; index++) - { - ref readonly var item = ref source[index]; - if (!predicate.Invoke(in item, index)) - return false; - } - return true; - } - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/AllRef/AllRef.Span.cs b/NetFabric.Hyperlinq/Quantifier/AllRef/AllRef.Span.cs deleted file mode 100644 index 87de90700..000000000 --- a/NetFabric.Hyperlinq/Quantifier/AllRef/AllRef.Span.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this Span source, FunctionIn predicate) - => source.AllRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AllRef(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source).AllRef(predicate); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool All(this Span source, FunctionIn predicate) - => source.AllAtRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AllAtRef(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source).AllAtRef(predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/Any/Any.ReadOnlyList.cs b/NetFabric.Hyperlinq/Quantifier/Any/Any.ReadOnlyList.cs deleted file mode 100644 index a4cab4ec1..000000000 --- a/NetFabric.Hyperlinq/Quantifier/Any/Any.ReadOnlyList.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TList source) - where TList : struct, IReadOnlyList - => source.Any(0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool Any(this TList source, int offset, int count) - where TList : struct, IReadOnlyList - => count is not 0; - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TList source, Func predicate) - where TList : struct, IReadOnlyList - => source.Any(predicate, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool Any(this TList source, Func predicate, int offset, int count) - where TList : struct, IReadOnlyList - => source.Any>(new FunctionWrapper(predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TList source, TPredicate predicate) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source.Any(predicate, 0, source.Count); - - static bool Any(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (predicate.Invoke(item)) - return true; - } - return false; - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TList source, Func predicate) - where TList : struct, IReadOnlyList - => source.Any(predicate, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool Any(this TList source, Func predicate, int offset, int count) - where TList : struct, IReadOnlyList - => source.AnyAt>(new FunctionWrapper(predicate), offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AnyAt(this TList source, TPredicate predicate) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - => source.AnyAt(predicate, 0, source.Count); - - static bool AnyAt(this TList source, TPredicate predicate, int offset, int count) - where TList : struct, IReadOnlyList - where TPredicate : struct, IFunction - { - if (offset is 0) - { - for (var index = 0; index < count; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - return true; - } - } - else - { - for (var index = 0; index < count; index++) - { - var item = source[index + offset]; - if (predicate.Invoke(item, index)) - return true; - } - } - return false; - } - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/Any/Any.Span.cs b/NetFabric.Hyperlinq/Quantifier/Any/Any.Span.cs deleted file mode 100644 index f157ae3a7..000000000 --- a/NetFabric.Hyperlinq/Quantifier/Any/Any.Span.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this Span source) - => source.Length is not 0; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this Span source, Func predicate) - => source.Any(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunction - => ((ReadOnlySpan)source).Any(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this Span source, Func predicate) - => source.AnyAt(new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AnyAt(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunction - => ((ReadOnlySpan)source).AnyAt(predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/Any/Any.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Quantifier/Any/Any.ValueReadOnlyCollection.cs deleted file mode 100644 index b1712c02e..000000000 --- a/NetFabric.Hyperlinq/Quantifier/Any/Any.ValueReadOnlyCollection.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueReadOnlyCollectionExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TEnumerable source) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => source.Count is not 0; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TEnumerable source, Func predicate) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => Any>(source, new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TEnumerable source, TPredicate predicate = default) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => source.Count is not 0 && ValueEnumerableExtensions.Any(source, predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this TEnumerable source, Func predicate) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - => AnyAt>(source, new FunctionWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AnyAt(this TEnumerable source, TPredicate predicate = default) - where TEnumerable : IValueReadOnlyCollection - where TEnumerator : struct, IEnumerator - where TPredicate : struct, IFunction - => source.Count is not 0 && ValueEnumerableExtensions.AnyAt(source, predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/AnyRef/AnyRef.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Quantifier/AnyRef/AnyRef.ReadOnlySpan.cs deleted file mode 100644 index 048a4a432..000000000 --- a/NetFabric.Hyperlinq/Quantifier/AnyRef/AnyRef.ReadOnlySpan.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this in ReadOnlySpan source, FunctionIn predicate) - => source.AnyRef(new FunctionInWrapper(predicate)); - - public static bool AnyRef(this ReadOnlySpan source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - { - foreach (ref readonly var item in source) - { - if (predicate.Invoke(in item)) - return true; - } - return false; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this in ReadOnlySpan source, FunctionIn predicate) - => source.AnyAtRef(new FunctionInWrapper(predicate)); - - public static bool AnyAtRef(this ReadOnlySpan source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - { - for (var index = 0; index < source.Length; index++) - { - ref readonly var item = ref source[index]; - if (predicate.Invoke(in item, index)) - return true; - } - return false; - } - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/AnyRef/AnyRef.Span.cs b/NetFabric.Hyperlinq/Quantifier/AnyRef/AnyRef.Span.cs deleted file mode 100644 index 1c95df676..000000000 --- a/NetFabric.Hyperlinq/Quantifier/AnyRef/AnyRef.Span.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this Span source, FunctionIn predicate) - => source.AnyRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AnyRef(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source).AnyRef(predicate); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Any(this Span source, FunctionIn predicate) - => source.AnyAtRef(new FunctionInWrapper(predicate)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool AnyAtRef(this Span source, TPredicate predicate = default) - where TPredicate : struct, IFunctionIn - => ((ReadOnlySpan)source).AnyAtRef(predicate); - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlyList.cs b/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlyList.cs deleted file mode 100644 index 4eff630ea..000000000 --- a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlyList.cs +++ /dev/null @@ -1,161 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.Design; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - public static bool Contains(this TList source, TSource value, IEqualityComparer? comparer = default) - where TList : struct, IReadOnlyList - => source.Contains(value, comparer, 0, source.Count); - - static bool Contains(this TList source, TSource value, IEqualityComparer? comparer, int offset, int count) - where TList : struct, IReadOnlyList - { - if (count is 0) - return false; - - if (comparer is null || ReferenceEquals(comparer, EqualityComparer.Default)) - { - if (offset is 0 && count == source.Count && source is ICollection collection) - return collection.Contains(value); - - if (Utils.IsValueType()) - return DefaultContains(source, value, offset, count); - } - - return ComparerContains(source, value, comparer, offset, count); - - static bool DefaultContains(TList source, TSource value, int offset, int count) - { - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (EqualityComparer.Default.Equals(item, value)) - return true; - } - return false; - } - - static bool ComparerContains(TList source, TSource value, IEqualityComparer? comparer, int offset, int count) - { - comparer ??= EqualityComparer.Default; - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (comparer.Equals(item, value)) - return true; - } - return false; - } - } - - static bool Contains(this TList source, TResult value, IEqualityComparer? comparer, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - return count switch - { - 0 => false, - _ => Utils.UseDefault(comparer) - ? ValueContains(source, value, selector, offset, count) - : ReferenceContains(source, value, comparer, selector, offset, count) - }; - - static bool ValueContains(TList source, TResult value, TSelector selector, int offset, int count) - { - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (EqualityComparer.Default.Equals(selector.Invoke(item), value)) - return true; - } - return false; - } - - static bool ReferenceContains(TList source, TResult value, IEqualityComparer? comparer, TSelector selector, int offset, int count) - { - comparer ??= EqualityComparer.Default; - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - if (comparer.Equals(selector.Invoke(item), value)) - return true; - } - return false; - } - } - - - static bool ContainsAt(this TList source, TResult value, IEqualityComparer? comparer, TSelector selector, int offset, int count) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - return count switch - { - 0 => false, - _ => Utils.UseDefault(comparer) - ? ValueContains(source, value, selector, offset, count) - : ReferenceContains(source, value, comparer, selector, offset, count) - }; - - static bool ValueContains(TList source, TResult value, TSelector selector, int offset, int count) - { - var end = count; - if (offset is 0) - { - for (var index = 0; index < end; index++) - { - var item = source[index]; - if (EqualityComparer.Default.Equals(selector.Invoke(item, index), value)) - return true; - } - } - else - { - for (var index = 0; index < end; index++) - { - var item = source[index + offset]; - if (EqualityComparer.Default.Equals(selector.Invoke(item, index), value)) - return true; - } - } - return false; - } - - static bool ReferenceContains(TList source, TResult value, IEqualityComparer? comparer, TSelector selector, int offset, int count) - { - comparer ??= EqualityComparer.Default; - var end = count; - if (offset is 0) - { - for (var index = 0; index < end; index++) - { - var item = source[index]; - if (comparer.Equals(selector.Invoke(item, index), value)) - return true; - } - } - else - { - for (var index = 0; index < end; index++) - { - var item = source[index + offset]; - if (comparer.Equals(selector.Invoke(item, index), value)) - return true; - } - } - return false; - } - } - } -} - diff --git a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.Span.cs b/NetFabric.Hyperlinq/Quantifier/Contains/Contains.Span.cs deleted file mode 100644 index 95679aa69..000000000 --- a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.Span.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Contains(this Span source, TSource value, IEqualityComparer? comparer = default) - => ((ReadOnlySpan)source).Contains(value, comparer); - - } -} - diff --git a/NetFabric.Hyperlinq/Resource.Designer.cs b/NetFabric.Hyperlinq/Resource.Designer.cs index 194580233..f8a357e32 100644 --- a/NetFabric.Hyperlinq/Resource.Designer.cs +++ b/NetFabric.Hyperlinq/Resource.Designer.cs @@ -1,7 +1,6 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -12,46 +11,32 @@ namespace NetFabric.Hyperlinq { using System; - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resource { - private static global::System.Resources.ResourceManager resourceMan; + private static System.Resources.ResourceManager resourceMan; - private static global::System.Globalization.CultureInfo resourceCulture; + private static System.Globalization.CultureInfo resourceCulture; - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resource() { } - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Resources.ResourceManager ResourceManager { get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NetFabric.Hyperlinq.Resource", typeof(Resource).Assembly); + if (object.Equals(null, resourceMan)) { + System.Resources.ResourceManager temp = new System.Resources.ResourceManager("NetFabric.Hyperlinq.Resource", typeof(Resource).Assembly); resourceMan = temp; } return resourceMan; } } - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -60,40 +45,10 @@ internal class Resource { } } - /// - /// Looks up a localized string similar to The array in the ArraySegment is null. - /// - internal static string ArraySegmentNull { - get { - return ResourceManager.GetString("ArraySegmentNull", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Destination array was not long enough. Check the destination index, length, and the array's lower bounds.. - /// internal static string DestinationNotLongEnough { get { return ResourceManager.GetString("DestinationNotLongEnough", resourceCulture); } } - - /// - /// Looks up a localized string similar to Sequence contains no elements. - /// - internal static string EmptySequence { - get { - return ResourceManager.GetString("EmptySequence", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Sequence contains more than one element. - /// - internal static string NotSingleSequence { - get { - return ResourceManager.GetString("NotSingleSequence", resourceCulture); - } - } } } diff --git a/NetFabric.Hyperlinq/Resource.resx b/NetFabric.Hyperlinq/Resource.resx index 05b1efb3f..d217097c0 100644 --- a/NetFabric.Hyperlinq/Resource.resx +++ b/NetFabric.Hyperlinq/Resource.resx @@ -1,132 +1,24 @@ - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - The array in the ArraySegment is null - - - Destination array was not long enough. Check the destination index, length, and the array's lower bounds. - - - Sequence contains no elements - - - Sequence contains more than one element - \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq/Set/Distinct/Distinct.AsyncValueEnumerable.cs deleted file mode 100644 index 805d6c2a6..000000000 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.AsyncValueEnumerable.cs +++ /dev/null @@ -1,212 +0,0 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class AsyncValueEnumerableExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static DistinctEnumerable Distinct( - this TEnumerable source, - IEqualityComparer? comparer = default) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - => new(source, comparer); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct DistinctEnumerable - : IAsyncValueEnumerable.Enumerator> - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - { - readonly TEnumerable source; - readonly IEqualityComparer? comparer; - - internal DistinctEnumerable(TEnumerable source, IEqualityComparer? comparer) - => (this.source, this.comparer) = (source, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - => new(in this, cancellationToken); - readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this, cancellationToken); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IAsyncEnumerator - , IAsyncStateMachine - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly - readonly IEqualityComparer? comparer; - Set set; - - int state; - AsyncValueTaskMethodBuilder builder; - bool s__1; - ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter u__1; - ValueTaskAwaiter u__2; - - internal Enumerator(in DistinctEnumerable enumerable, CancellationToken cancellationToken) - { - enumerator = enumerable.source.GetAsyncEnumerator(cancellationToken); - comparer = enumerable.comparer; - set = new Set(comparer); - - state = default; - builder = default; - s__1 = default; - u__1 = default; - u__2 = default; - } - - public readonly TSource Current - => enumerator.Current; - readonly TSource IAsyncEnumerator.Current - => enumerator.Current; - - //public async ValueTask MoveNextAsync() - //{ - // while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - // { - // if (set.Add(enumerator.Current)) - // return true; - // } - - // await DisposeAsync(); - // return false; - //} - - public ValueTask MoveNextAsync() - { - state = -1; - builder = AsyncValueTaskMethodBuilder.Create(); - builder.Start(ref this); - return builder.Task; - } - - public ValueTask DisposeAsync() - { - set.Dispose(); - return enumerator.DisposeAsync(); - } - - void IAsyncStateMachine.MoveNext() - { - var num = state; - bool result; - try - { - ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter awaiter; - if (num is 0) - { - awaiter = u__1; - u__1 = default; - num = state = -1; - goto IL_00c0; - } - if (num != 1) - { - goto IL_004c; - } - var awaiter2 = u__2; - u__2 = default; - num = state = -1; - goto IL_013c; - IL_00c0: - s__1 = awaiter.GetResult(); - if (!s__1) - { - awaiter2 = DisposeAsync().GetAwaiter(); - if (!awaiter2.IsCompleted) - { - num = state = 1; - u__2 = awaiter2; - builder.AwaitUnsafeOnCompleted(ref awaiter2, ref this); - return; - } - goto IL_013c; - } - if (!set.Add(enumerator.Current)) - { - goto IL_004c; - } - result = true; - goto end_IL_0007; - IL_004c: - awaiter = enumerator.MoveNextAsync().ConfigureAwait(false).GetAwaiter(); - if (!awaiter.IsCompleted) - { - num = state = 0; - u__1 = awaiter; - builder.AwaitUnsafeOnCompleted(ref awaiter, ref this); - return; - } - goto IL_00c0; - IL_013c: - awaiter2.GetResult(); - result = false; - end_IL_0007: - ; - } - catch (Exception exception) - { - state = -2; - builder.SetException(exception); - return; - } - state = -2; - builder.SetResult(result); - } - - void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) - { } - } - - readonly async ValueTask> FillSetAsync(CancellationToken cancellationToken) - { - var set = new Set(comparer); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - _ = set.Add(enumerator.Current); - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return set; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly async ValueTask CountAsync(CancellationToken cancellationToken = default) - => (await FillSetAsync(cancellationToken).ConfigureAwait(false)).Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ValueTask AnyAsync(CancellationToken cancellationToken = default) - => source.AnyAsync(cancellationToken); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly async ValueTask ToArrayAsync(CancellationToken cancellationToken = default) - => (await FillSetAsync(cancellationToken).ConfigureAwait(false)).ToArray(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly async ValueTask> ToArrayAsync(MemoryPool pool, CancellationToken cancellationToken = default) - => (await FillSetAsync(cancellationToken).ConfigureAwait(false)).ToArray(pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly async ValueTask> ToListAsync(CancellationToken cancellationToken = default) - => (await FillSetAsync(cancellationToken).ConfigureAwait(false)).ToList(); - } - } -} - diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyList.cs b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyList.cs deleted file mode 100644 index 4ab435ad2..000000000 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyList.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ReadOnlyListExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static DistinctEnumerable Distinct(this TList source, IEqualityComparer? comparer = default) - where TList : struct, IReadOnlyList - => source.Distinct(comparer, 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static DistinctEnumerable Distinct(this TList source, IEqualityComparer? comparer, int offset, int count) - where TList : struct, IReadOnlyList - => new(source, comparer, offset, count); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct DistinctEnumerable - : IValueEnumerable.Enumerator> - where TList : struct, IReadOnlyList - { - readonly TList source; - readonly IEqualityComparer? comparer; - readonly int offset; - readonly int count; - - internal DistinctEnumerable(TList source, IEqualityComparer? comparer, int offset, int count) - => (this.source, this.comparer, this.offset, this.count) = (source, comparer, offset, count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - readonly TList source; - Set set; - readonly int end; - int index; - - internal Enumerator(in DistinctEnumerable enumerable) - { - source = enumerable.source; - set = new Set(enumerable.comparer); - index = enumerable.offset - 1; - end = index + enumerable.count; - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source[index]; - } - readonly TSource IEnumerator.Current - => source[index]; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => source[index]; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (++index <= end) - { - if (set.Add(source[index])) - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() - => set.Dispose(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly Set GetSet() - { - using var set = new Set(comparer); - var end = offset + count; - for (var index = offset; index < end; index++) - { - var item = source[index]; - _ = set.Add(item); - } - return set; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public DistinctEnumerable Skip(int count) - { - var (skipCount, takeCount) = Utils.Skip(this.count, count); - return new DistinctEnumerable(source, comparer, offset + skipCount, takeCount); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public DistinctEnumerable Take(int count) - => new(source, comparer, offset, Utils.Take(this.count, count)); - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() - => count switch - { - 0 => 0, - _ => GetSet().Count - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any() - => count is not 0; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly TSource[] ToArray() - => count switch - { - 0 => Array.Empty(), - _ => GetSet().ToArray() - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly IMemoryOwner ToArray(MemoryPool pool) - => count switch - { - 0 => pool.RentSliced(0), - _ => GetSet().ToArray(pool) - }; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly List ToList() - => count switch - { - // ReSharper disable once HeapView.ObjectAllocation.Evident - 0 => new List(), - _ => GetSet().ToList() - }; - - public readonly bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) - { - comparer ??= EqualityComparer.Default; - - using var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } - } - } -} - diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.Span.cs b/NetFabric.Hyperlinq/Set/Distinct/Distinct.Span.cs deleted file mode 100644 index b7228fffe..000000000 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.Span.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SpanDistinctEnumerable Distinct(this Span source, IEqualityComparer? comparer = null) - => ((ReadOnlySpan)source).Distinct(comparer); - } -} - diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ValueEnumerable.cs b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ValueEnumerable.cs deleted file mode 100644 index 82d4c1bab..000000000 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ValueEnumerable.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using System.Buffers; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - public static partial class ValueEnumerableExtensions - { - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static DistinctEnumerable Distinct( - this TEnumerable source, - IEqualityComparer? comparer = default) - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - => new(source, comparer); - - [StructLayout(LayoutKind.Auto)] - public readonly partial struct DistinctEnumerable - : IValueEnumerable.Enumerator> - where TEnumerable : IValueEnumerable - where TEnumerator : struct, IEnumerator - { - readonly TEnumerable source; - readonly IEqualityComparer? comparer; - - internal DistinctEnumerable(TEnumerable source, IEqualityComparer? comparer) - => (this.source, this.comparer) = (source, comparer); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly Enumerator GetEnumerator() - => new(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - readonly IEnumerator IEnumerable.GetEnumerator() - // ReSharper disable once HeapView.BoxingAllocation - => new Enumerator(in this); - - [StructLayout(LayoutKind.Auto)] - public struct Enumerator - : IEnumerator - { - [SuppressMessage("Style", "IDE0044:Add readonly modifier")] - TEnumerator enumerator; // do not make readonly - readonly IEqualityComparer? comparer; - Set set; - - internal Enumerator(in DistinctEnumerable enumerable) - { - enumerator = enumerable.source.GetEnumerator(); - comparer = enumerable.comparer; - set = new Set(comparer); - } - - public readonly TSource Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => enumerator.Current; - } - readonly TSource IEnumerator.Current - => enumerator.Current; - readonly object? IEnumerator.Current - // ReSharper disable once HeapView.PossibleBoxingAllocation - => enumerator.Current; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (enumerator.MoveNext()) - { - if (set.Add(enumerator.Current)) - return true; - } - return false; - } - - [ExcludeFromCodeCoverage] - public readonly void Reset() - => Throw.NotSupportedException(); - - public void Dispose() - { - enumerator.Dispose(); - set.Dispose(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly Set GetSet() - { - using var set = new Set(comparer); - using var enumerator = source.GetEnumerator(); - while (enumerator.MoveNext()) - _ = set.Add(enumerator.Current); - return set; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly int Count() - => GetSet().Count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Any() - => source.Any(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly TSource[] ToArray() - => GetSet().ToArray(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly IMemoryOwner ToArray(MemoryPool pool) - => GetSet().ToArray(pool); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly List ToList() - => GetSet().ToList(); - } - } -} - diff --git a/NetFabric.Hyperlinq/SyntaxReceiver.cs b/NetFabric.Hyperlinq/SyntaxReceiver.cs new file mode 100644 index 000000000..56fd3dd59 --- /dev/null +++ b/NetFabric.Hyperlinq/SyntaxReceiver.cs @@ -0,0 +1,33 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + class SyntaxReceiver : ISyntaxReceiver + { + readonly ImmutableHashSet memberAccessNames; + + public SyntaxReceiver(ImmutableHashSet memberAccessNames) + => this.memberAccessNames = memberAccessNames; + + public List MemberAccessExpressions { get; } = new(); + + public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + { + switch (syntaxNode) + { + case MemberAccessExpressionSyntax { Name: var memberName } memberAccessExpression: + if (memberAccessExpression.Kind() == SyntaxKind.SimpleMemberAccessExpression + && memberAccessNames.Contains(memberName.Identifier.ValueText)) + { + // It's a SimpleMemberAccessExpression and its name is in memberAccessNames collection + MemberAccessExpressions.Add(memberAccessExpression); + } + break; + } + } + } +} diff --git a/NetFabric.Hyperlinq/TypeSymbolsCache.cs b/NetFabric.Hyperlinq/TypeSymbolsCache.cs new file mode 100644 index 000000000..f3694a1e6 --- /dev/null +++ b/NetFabric.Hyperlinq/TypeSymbolsCache.cs @@ -0,0 +1,28 @@ +using Ben.Collections; +using Microsoft.CodeAnalysis; +using System; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + class TypeSymbolsCache + { + readonly Compilation compilation; + readonly TypeDictionary cacheByType = new(); + + public TypeSymbolsCache(Compilation compilation) + => this.compilation = compilation; + + public INamedTypeSymbol? this[Type type] + { + get + { + if (cacheByType.TryGetValue(type, out var symbol)) + return symbol; + + symbol = compilation.GetTypeByMetadataName(type.FullName); + cacheByType[type] = symbol; + return symbol; + } + } + } +} diff --git a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlySpan.cs deleted file mode 100644 index d282df0c2..000000000 --- a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilder.ReadOnlySpan.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Buffers; -using System.Diagnostics; - -namespace NetFabric.Hyperlinq -{ - public static partial class ArrayExtensions - { - - static LargeArrayBuilder ToArrayBuilder(ReadOnlySpan source, TPredicate predicate, ArrayPool arrayPool) - where TPredicate: struct, IFunction - { - var builder = new LargeArrayBuilder(arrayPool); - foreach (var item in source) - { - if (predicate.Invoke(item)) - builder.Add(item); - } - return builder; - } - - static LargeArrayBuilder ToArrayBuilderRef(ReadOnlySpan source, TPredicate predicate, ArrayPool arrayPool) - where TPredicate : struct, IFunctionIn - { - var builder = new LargeArrayBuilder(arrayPool); - foreach (ref readonly var item in source) - { - if (predicate.Invoke(in item)) - builder.AddRef(in item); - } - return builder; - } - - static LargeArrayBuilder ToArrayBuilderAt(ReadOnlySpan source, TPredicate predicate, ArrayPool arrayPool) - where TPredicate: struct, IFunction - { - var builder = new LargeArrayBuilder(arrayPool); - for (var index = 0; index < source.Length; index++) - { - var item = source[index]; - if (predicate.Invoke(item, index)) - builder.Add(item); - } - return builder; - } - - static LargeArrayBuilder ToArrayBuilderAtRef(ReadOnlySpan source, TPredicate predicate, ArrayPool arrayPool) - where TPredicate : struct, IFunctionIn - { - var builder = new LargeArrayBuilder(arrayPool); - for (var index = 0; index < source.Length; index++) - { - ref readonly var item = ref source[index]; - if (predicate.Invoke(in item, index)) - builder.AddRef(in item); - } - return builder; - } - - static LargeArrayBuilder ToArrayBuilder(ReadOnlySpan source, TPredicate predicate, TSelector selector, ArrayPool arrayPool) - where TPredicate: struct, IFunction - where TSelector: struct, IFunction - { - var builder = new LargeArrayBuilder(arrayPool); - foreach (var item in source) - { - if (predicate.Invoke(item)) - builder.Add(selector.Invoke(item)); - } - return builder; - } - - static LargeArrayBuilder ToArrayBuilderRef(ReadOnlySpan source, TPredicate predicate, TSelector selector, ArrayPool arrayPool) - where TPredicate : struct, IFunctionIn - where TSelector : struct, IFunctionIn - { - var builder = new LargeArrayBuilder(arrayPool); - foreach (ref readonly var item in source) - { - if (predicate.Invoke(in item)) - builder.Add(selector.Invoke(in item)); - } - return builder; - } - } -} diff --git a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilderAsync.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilderAsync.AsyncValueEnumerable.cs deleted file mode 100644 index 1deb76efa..000000000 --- a/NetFabric.Hyperlinq/Utils/ArrayBuilder/ToArrayBuilderAsync.AsyncValueEnumerable.cs +++ /dev/null @@ -1,320 +0,0 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace NetFabric.Hyperlinq -{ - public static partial class AsyncValueEnumerableExtensions - { - - public static async ValueTask ToArrayBuilderAsync(this TEnumerable source, CancellationToken cancellationToken = default) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - { - cancellationToken.ThrowIfCancellationRequested(); - builder.Add(enumerator.Current); - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(); - } - - public static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, MemoryPool pool, CancellationToken cancellationToken = default) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - { - cancellationToken.ThrowIfCancellationRequested(); - builder.Add(enumerator.Current); - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(pool); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - static async ValueTask ToArrayBuilderAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TPredicate: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - { - cancellationToken.ThrowIfCancellationRequested(); - - var item = enumerator.Current; - if (await predicate.InvokeAsync(item, cancellationToken).ConfigureAwait(false)) - builder.Add(item); - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(); - } - - static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, TPredicate predicate, MemoryPool pool, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TPredicate: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - { - cancellationToken.ThrowIfCancellationRequested(); - - var item = enumerator.Current; - if (await predicate.InvokeAsync(item, cancellationToken).ConfigureAwait(false)) - builder.Add(item); - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(pool); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - static async ValueTask ToArrayBuilderAtAsync(this TEnumerable source, TPredicate predicate, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TPredicate: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - checked - { - for (var index = 0; await enumerator.MoveNextAsync().ConfigureAwait(false); index++) - { - cancellationToken.ThrowIfCancellationRequested(); - - var item = enumerator.Current; - if (await predicate.InvokeAsync(item, index, cancellationToken).ConfigureAwait(false)) - builder.Add(item); - } - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(); - } - - static async ValueTask> ToArrayBuilderAtAsync(this TEnumerable source, TPredicate predicate, MemoryPool pool, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TPredicate: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - checked - { - for (var index = 0; await enumerator.MoveNextAsync().ConfigureAwait(false); index++) - { - cancellationToken.ThrowIfCancellationRequested(); - - var item = enumerator.Current; - if (await predicate.InvokeAsync(item, index, cancellationToken).ConfigureAwait(false)) - builder.Add(item); - } - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(pool); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - static async ValueTask ToArrayBuilderAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TSelector: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - { - cancellationToken.ThrowIfCancellationRequested(); - - builder.Add(await selector.InvokeAsync(enumerator.Current, cancellationToken).ConfigureAwait(false)); - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(); - } - - static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, TSelector selector, MemoryPool pool, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TSelector: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - { - cancellationToken.ThrowIfCancellationRequested(); - - builder.Add(await selector.InvokeAsync(enumerator.Current, cancellationToken).ConfigureAwait(false)); - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(pool); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - static async ValueTask ToArrayBuilderAtAsync(this TEnumerable source, TSelector selector, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TSelector: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - checked - { - for (var index = 0; await enumerator.MoveNextAsync().ConfigureAwait(false); index++) - { - cancellationToken.ThrowIfCancellationRequested(); - - builder.Add(await selector.InvokeAsync(enumerator.Current, index, cancellationToken).ConfigureAwait(false)); - } - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(); - } - - static async ValueTask> ToArrayBuilderAtAsync(this TEnumerable source, TSelector selector, MemoryPool pool, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TSelector: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - checked - { - for (var index = 0; await enumerator.MoveNextAsync().ConfigureAwait(false); index++) - { - cancellationToken.ThrowIfCancellationRequested(); - - builder.Add(await selector.InvokeAsync(enumerator.Current, index, cancellationToken).ConfigureAwait(false)); - } - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(pool); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////// - - static async ValueTask ToArrayBuilderAsync(this TEnumerable source, TPredicate predicate, TSelector selector, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TPredicate: struct, IAsyncFunction - where TSelector: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - { - cancellationToken.ThrowIfCancellationRequested(); - - var item = enumerator.Current; - if (await predicate.InvokeAsync(item, cancellationToken).ConfigureAwait(false)) - builder.Add(await selector.InvokeAsync(item, cancellationToken).ConfigureAwait(false)); - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(); - } - - static async ValueTask> ToArrayBuilderAsync(this TEnumerable source, TPredicate predicate, TSelector selector, MemoryPool pool, CancellationToken cancellationToken) - where TEnumerable : IAsyncValueEnumerable - where TEnumerator : struct, IAsyncEnumerator - where TPredicate: struct, IAsyncFunction - where TSelector: struct, IAsyncFunction - { - var builder = new LargeArrayBuilder(ArrayPool.Shared); - var enumerator = source.GetAsyncEnumerator(cancellationToken); - try - { - while (await enumerator.MoveNextAsync().ConfigureAwait(false)) - { - cancellationToken.ThrowIfCancellationRequested(); - - var item = enumerator.Current; - if (await predicate.InvokeAsync(item, cancellationToken).ConfigureAwait(false)) - builder.Add(await selector.InvokeAsync(item, cancellationToken).ConfigureAwait(false)); - } - } - finally - { - await enumerator.DisposeAsync().ConfigureAwait(false); - } - return builder.ToArray(pool); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Utils/ArrayPoolExtensions.cs b/NetFabric.Hyperlinq/Utils/ArrayPoolExtensions.cs deleted file mode 100644 index 4fd1ffd90..000000000 --- a/NetFabric.Hyperlinq/Utils/ArrayPoolExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Buffers; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - static class ArrayPool - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ArraySegment RentSliced(this ArrayPool pool, int count) - => new(pool.Rent(count), 0, count); - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator/Utils/AttributeExtensions.cs b/NetFabric.Hyperlinq/Utils/AttributeExtensions.cs similarity index 100% rename from NetFabric.Hyperlinq.SourceGenerator/Utils/AttributeExtensions.cs rename to NetFabric.Hyperlinq/Utils/AttributeExtensions.cs diff --git a/NetFabric.Hyperlinq/Utils/CodeBuilder.cs b/NetFabric.Hyperlinq/Utils/CodeBuilder.cs new file mode 100644 index 000000000..1d81877fb --- /dev/null +++ b/NetFabric.Hyperlinq/Utils/CodeBuilder.cs @@ -0,0 +1,152 @@ +using System; +using System.IO; +using System.Reflection; +using System.Text; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + class CodeBuilder + { + const string indentation = " "; + + readonly StringBuilder builder = new(); + int currentLevel = 0; + + public bool IsUnitTest { get; init; } = false; + + StringBuilder AppendIndents() + { + for (var level = 0; level < currentLevel; level++) + _ = builder.Append(indentation); + + return builder; + } + + public CodeBuilder Indent() + { + _ = builder.Append(indentation); + return this; + } + + public CodeBuilder Line() + { + _ = builder.AppendLine(); + return this; + } + + public CodeBuilder Line(char text) + { + _ = AppendIndents().Append(text).AppendLine(); + return this; + } + + public CodeBuilder Line(string text) + { + _ = AppendIndents().AppendLine(text); + return this; + } + + public CodeBuilder Line(Action line) + { + _ = AppendIndents(); + line(builder); + _ = Line(); + return this; + } + + public IDisposable Block() + { + _ = Line('{'); + currentLevel++; + // ReSharper disable once HeapView.ObjectAllocation.Evident + return new CloseBlock(this); + } + + public IDisposable Block(string text) + => Line(text).Block(); + + public CodeBuilder MethodBlock(string header, Action block) + { + using (Block(header)) + { + block(this); + } + return this; + } + + public CodeBuilder IfBlock(string condition, Action block) + { + using (Block($"if ({condition})")) + { + block(this); + } + return this; + } + + public CodeBuilder IfBlock(string condition, Action trueBlock, Action falseBlock) + { + using (Block($"if ({condition})")) + { + trueBlock(this); + } + using (Block("else")) + { + falseBlock(this); + } + return this; + } + + public CodeBuilder ForEachBlock(string text, Action block) + { + using (Block($"foreach ({text})")) + { + block(this); + } + return this; + } + + public CodeBuilder ForBlock(string text, Action block) + { + using (Block($"for ({text})")) + { + block(this); + } + return this; + } + + public CodeBuilder WhileBlock(string text, Action block) + { + using (Block($"while ({text})")) + { + block(this); + } + return this; + } + + public CodeBuilder CheckedBlock(Action block) + { + using (Block("checked")) + { + block(this); + } + return this; + } + + class CloseBlock : IDisposable + { + readonly CodeBuilder builder; + + public CloseBlock(CodeBuilder builder) + => this.builder = builder; + + public void Dispose() + { + builder.currentLevel--; + _ = builder.Line('}'); + } + } + + public override string ToString() + => builder.ToString(); + } +} diff --git a/NetFabric.Hyperlinq/Utils/CodeBuilderExtensions.cs b/NetFabric.Hyperlinq/Utils/CodeBuilderExtensions.cs new file mode 100644 index 000000000..8c9725da7 --- /dev/null +++ b/NetFabric.Hyperlinq/Utils/CodeBuilderExtensions.cs @@ -0,0 +1,25 @@ +using System; +using System.Reflection; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + static class CodeBuilderExtensions + { + static readonly string assemblyName = typeof(CodeBuilder).Assembly + .GetName().Name; + static readonly string assemblyVersion = typeof(CodeBuilder).Assembly + .GetCustomAttribute()?.InformationalVersion + ?? string.Empty; + + public static CodeBuilder GeneratedCodeMethodAttributes(this CodeBuilder builder) + => builder.IsUnitTest + ? builder // do nothing + : builder.Line($"[GeneratedCode(\"{assemblyName}\", \"{assemblyVersion}\")]") + .Line("[DebuggerNonUserCode]") + .Line("[ExcludeFromCodeCoverage]") + .Line("[EditorBrowsable(EditorBrowsableState.Never)]"); + + public static CodeBuilder AggressiveInliningAttribute(this CodeBuilder builder) + => builder.Line("[MethodImpl(MethodImplOptions.AggressiveInlining)]"); + } +} diff --git a/NetFabric.Hyperlinq/Utils/Copy/Copy.ReadOnlyList.cs b/NetFabric.Hyperlinq/Utils/Copy/Copy.ReadOnlyList.cs deleted file mode 100644 index e1e25c18f..000000000 --- a/NetFabric.Hyperlinq/Utils/Copy/Copy.ReadOnlyList.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; - -namespace NetFabric.Hyperlinq -{ - static partial class ReadOnlyListExtensions - { - public static void Copy(TList source, int sourceOffset, Span destination, int count) - where TList : struct, IReadOnlyList - { - Debug.Assert(source.Count >= sourceOffset); - Debug.Assert(destination.Length >= count); - - if (count is 0) - return; - - if (sourceOffset is 0) - { - for (var index = 0; index < count; index++) - destination[index] = source[index]; - } - else - { - for (var index = 0; index < count; index++) - destination[index] = source[index + sourceOffset]; - } - } - - public static void Copy(TList source, int sourceOffset, Span destination, int count, TSelector selector = default) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - Debug.Assert(source.Count >= sourceOffset); - Debug.Assert(destination.Length >= count); - - if (count is 0) - return; - - if (sourceOffset is 0) - { - for (var index = 0; index < count; index++) - destination[index] = selector.Invoke(source[index]); - } - else - { - for (var index = 0; index < count; index++) - destination[index] = selector.Invoke(source[index + sourceOffset]); - } - } - - public static void CopyAt(TList source, int sourceOffset, Span destination, int count, TSelector selector = default) - where TList : struct, IReadOnlyList - where TSelector : struct, IFunction - { - Debug.Assert(source.Count >= sourceOffset); - Debug.Assert(destination.Length >= count); - - if (count is 0) - return; - - if (sourceOffset is 0) - { - for (var index = 0; index < count; index++) - destination[index] = selector.Invoke(source[index], index); - } - else - { - for (var index = 0; index < count; index++) - destination[index] = selector.Invoke(source[index + sourceOffset], index); - } - } - - } -} diff --git a/NetFabric.Hyperlinq/Utils/DictionarySet.cs b/NetFabric.Hyperlinq/Utils/DictionarySet.cs new file mode 100644 index 000000000..4f13b7371 --- /dev/null +++ b/NetFabric.Hyperlinq/Utils/DictionarySet.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + class DictionarySet + where TKey : notnull + { + readonly Dictionary> dictionary = new(); + + public int Count { get; private set; } + + public void Add(TKey key, TValue value) + { + if (!dictionary.TryGetValue(key, out var list)) + { + list = new List(); + dictionary.Add(key, list); + } + list.Add(value); + Count++; + } + + public bool TryGetValue(TKey key, [NotNullWhen(true)] out IReadOnlyList? values) + { + if (dictionary.TryGetValue(key, out var list)) + { + values = list; + return true; + } + + values = default; + return false; + } + } +} diff --git a/NetFabric.Hyperlinq/Utils/Generator/GeneratorIgnoreAttribute.cs b/NetFabric.Hyperlinq/Utils/Generator/GeneratorIgnoreAttribute.cs deleted file mode 100644 index d7e78203d..000000000 --- a/NetFabric.Hyperlinq/Utils/Generator/GeneratorIgnoreAttribute.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; - -namespace NetFabric.Hyperlinq -{ - [ExcludeFromCodeCoverage] - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method)] - public sealed class GeneratorIgnoreAttribute : Attribute - { - public bool Value { get; } - - public GeneratorIgnoreAttribute(bool value = true) - => Value = value; - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Utils/GenericsOperator.cs b/NetFabric.Hyperlinq/Utils/GenericsOperator.cs deleted file mode 100644 index 345187874..000000000 --- a/NetFabric.Hyperlinq/Utils/GenericsOperator.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - static class GenericsOperator - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TValue Add(TValue a, TValue b) - where TValue : struct - { - if (typeof(TValue) == typeof(byte)) - return (TValue)(object)((byte)(object)a + (byte)(object)b); - - if (typeof(TValue) == typeof(sbyte)) - return (TValue)(object)((sbyte)(object)a + (sbyte)(object)b); - - if (typeof(TValue) == typeof(ushort)) - return (TValue)(object)((ushort)(object)a + (ushort)(object)b); - - if (typeof(TValue) == typeof(short)) - return (TValue)(object)((short)(object)a + (short)(object)b); - - if (typeof(TValue) == typeof(uint)) - return (TValue)(object)((uint)(object)a + (uint)(object)b); - - if (typeof(TValue) == typeof(int)) - return (TValue)(object)((int)(object)a + (int)(object)b); - - if (typeof(TValue) == typeof(ulong)) - return (TValue)(object)((ulong)(object)a + (ulong)(object)b); - - if (typeof(TValue) == typeof(long)) - return (TValue)(object)((long)(object)a + (long)(object)b); - - if (typeof(TValue) == typeof(float)) - return (TValue)(object)((float)(object)a + (float)(object)b); - - if (typeof(TValue) == typeof(double)) - return (TValue)(object)((double)(object)a + (double)(object)b); - - return Throw.NotSupportedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TValue AddNullable(TNullableValue a, TValue b) - where TValue : struct - { - if (typeof(TNullableValue) == typeof(int?) && typeof(TValue) == typeof(int)) - return (TValue)(object)(((int?)(object)a).GetValueOrDefault() + (int)(object)b); - - if (typeof(TNullableValue) == typeof(int) && typeof(TValue) == typeof(int)) - return (TValue)(object)((int)(object)a! + (int)(object)b); - - if (typeof(TNullableValue) == typeof(long?) && typeof(TValue) == typeof(long)) - return (TValue)(object)(((long?)(object)a).GetValueOrDefault() + (long)(object)b); - - if (typeof(TNullableValue) == typeof(long) && typeof(TValue) == typeof(long)) - return (TValue)(object)((long)(object)a! + (long)(object)b); - - if (typeof(TNullableValue) == typeof(float?) && typeof(TValue) == typeof(float)) - return (TValue)(object)(((float?)(object)a).GetValueOrDefault() + (float)(object)b); - - if (typeof(TNullableValue) == typeof(float) && typeof(TValue) == typeof(float)) - return (TValue)(object)((float)(object)a! + (float)(object)b); - - if (typeof(TNullableValue) == typeof(double?) && typeof(TValue) == typeof(double)) - return (TValue)(object)(((double?)(object)a).GetValueOrDefault() + (double)(object)b); - - if (typeof(TNullableValue) == typeof(double) && typeof(TValue) == typeof(double)) - return (TValue)(object)((double)(object)a! + (double)(object)b); - - if (typeof(TNullableValue) == typeof(decimal?) && typeof(TValue) == typeof(decimal)) - return (TValue)(object)(((decimal?)(object)a).GetValueOrDefault() + (decimal)(object)b); - - if (typeof(TNullableValue) == typeof(decimal) && typeof(TValue) == typeof(decimal)) - return (TValue)(object)((decimal)(object)a! + (decimal)(object)b); - - return Throw.NotSupportedException(); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Equals(TValue a, TValue b) - where TValue : struct - { - if (typeof(TValue) == typeof(byte)) - return (byte)(object)a == (byte)(object)b; - - if (typeof(TValue) == typeof(sbyte)) - return (sbyte)(object)a == (sbyte)(object)b; - - if (typeof(TValue) == typeof(ushort)) - return (ushort)(object)a == (ushort)(object)b; - - if (typeof(TValue) == typeof(short)) - return (short)(object)a == (short)(object)b; - - if (typeof(TValue) == typeof(uint)) - return (uint)(object)a == (uint)(object)b; - - if (typeof(TValue) == typeof(int)) - return (int)(object)a == (int)(object)b; - - if (typeof(TValue) == typeof(ulong)) - return (ulong)(object)a == (ulong)(object)b; - - if (typeof(TValue) == typeof(long)) - return (long)(object)a == (long)(object)b; - - if (typeof(TValue) == typeof(float)) - return (float)(object)a == (float)(object)b; - - if (typeof(TValue) == typeof(double)) - return (double)(object)a == (double)(object)b; - - return Throw.NotSupportedException(); - } - } -} diff --git a/NetFabric.Hyperlinq/Utils/IndexOf/IndexOf.ReadOnlyList.cs b/NetFabric.Hyperlinq/Utils/IndexOf/IndexOf.ReadOnlyList.cs deleted file mode 100644 index 40df061ce..000000000 --- a/NetFabric.Hyperlinq/Utils/IndexOf/IndexOf.ReadOnlyList.cs +++ /dev/null @@ -1,213 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - static partial class ReadOnlyListExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int IndexOf(IReadOnlyList source, TSource item, int offset, int count) - { - if (count is 0) - return -1; - - if (offset is 0 && count == source.Count && source is IList list) - return list.IndexOf(item); - - var end = offset + count; - if (Utils.IsValueType()) - { - for (var index = offset; index < end; index++) - { - var arrayItem = source[index]; - if (EqualityComparer.Default.Equals(arrayItem, item)) - return index - offset; - } - } - else - { - var defaultComparer = EqualityComparer.Default; - for (var index = offset; index < end; index++) - { - var arrayItem = source[index]; - if (defaultComparer.Equals(arrayItem, item)) - return index - offset; - } - } - - return -1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int IndexOf(IReadOnlyList source, TResult item, TSelector selector, int offset, int count) - where TSelector : struct, IFunction - { - if (count is 0) - return -1; - - var end = offset + count; - if (Utils.IsValueType()) - { - for (var index = offset; index < end; index++) - { - var arrayItem = source[index]; - if (EqualityComparer.Default.Equals(selector.Invoke(arrayItem), item)) - return index - offset; - } - } - else - { - var defaultComparer = EqualityComparer.Default; - for (var index = offset; index < end; index++) - { - var arrayItem = source[index]; - if (defaultComparer.Equals(selector.Invoke(arrayItem), item)) - return index - offset; - } - } - - return -1; - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int IndexOfRef(IReadOnlyList source, TResult item, TSelector selector, int offset, int count) - where TSelector : struct, IFunctionIn - { - if (count is 0) - return -1; - - var end = offset + count; - if (Utils.IsValueType()) - { - for (var index = offset; index < end; index++) - { - var arrayItem = source[index]; - if (EqualityComparer.Default.Equals(selector.Invoke(in arrayItem), item)) - return index - offset; - } - } - else - { - var defaultComparer = EqualityComparer.Default; - for (var index = offset; index < end; index++) - { - var arrayItem = source[index]; - if (defaultComparer.Equals(selector.Invoke(in arrayItem), item)) - return index - offset; - } - } - - return -1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int IndexOfAt(IReadOnlyList source, TResult item, TSelector selector, int offset, int count) - where TSelector : struct, IFunction - { - if (count is 0) - return -1; - - if (Utils.IsValueType()) - { - if (offset is 0) - { - for (var index = 0; index < count; index++) - { - var listItem = source[index]; - if (EqualityComparer.Default.Equals(selector.Invoke(listItem, index), item)) - return index; - } - } - else - { - for (var index = 0; index < count; index++) - { - var listItem = source[index + offset]; - if (EqualityComparer.Default.Equals(selector.Invoke(listItem, index), item)) - return index; - } - } - } - else - { - var defaultComparer = EqualityComparer.Default; - - if (offset is 0) - { - for (var index = 0; index < count; index++) - { - var listItem = source[index]; - if (defaultComparer.Equals(selector.Invoke(listItem, index), item)) - return index; - } - } - else - { - for (var index = 0; index < count; index++) - { - var listItem = source[index + offset]; - if (defaultComparer.Equals(selector.Invoke(listItem, index), item)) - return index; - } - } - } - return -1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int IndexOfAtRef(IReadOnlyList source, TResult item, TSelector selector, int offset, int count) - where TSelector : struct, IFunctionIn - { - if (count is 0) - return -1; - - if (Utils.IsValueType()) - { - if (offset is 0) - { - for (var index = 0; index < count; index++) - { - var listItem = source[index]; - if (EqualityComparer.Default.Equals(selector.Invoke(in listItem, index), item)) - return index; - } - } - else - { - for (var index = 0; index < count; index++) - { - var listItem = source[index + offset]; - if (EqualityComparer.Default.Equals(selector.Invoke(in listItem, index), item)) - return index; - } - } - } - else - { - var defaultComparer = EqualityComparer.Default; - - if (offset is 0) - { - for (var index = 0; index < count; index++) - { - var listItem = source[index]; - if (defaultComparer.Equals(selector.Invoke(in listItem, index), item)) - return index; - } - } - else - { - for (var index = 0; index < count; index++) - { - var listItem = source[index + offset]; - if (defaultComparer.Equals(selector.Invoke(in listItem, index), item)) - return index; - } - } - } - return -1; - } - } -} diff --git a/NetFabric.Hyperlinq/Utils/ListExtensions.cs b/NetFabric.Hyperlinq/Utils/ListExtensions.cs deleted file mode 100644 index d0ff148fe..000000000 --- a/NetFabric.Hyperlinq/Utils/ListExtensions.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NetFabric.Hyperlinq -{ - static class ListExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ArraySegment AsArraySegment(this List source) - => new(source.GetItems(), 0, source.Count); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span AsSpan(this List source) -#if NET5_0 - => CollectionsMarshal.AsSpan(source); -#else - => source.GetItems().AsSpan().Slice(0, source.Count); -#endif - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Memory AsMemory(this List source) - => source.GetItems().AsMemory().Slice(0, source.Count); - - - public static List AsList(this TSource[] source) - { - var result = new List(); - var layout = Unsafe.As, ListLayout>(ref result); - layout.Items = source; - layout.Size = source.Length; - result.Capacity = source.Length; - return result; - } - - // ReSharper disable once ClassNeverInstantiated.Local -#if NET5_0 - [SkipLocalsInit] -#endif - class ListLayout - { - public TSource[]? Items; -#if !(NETCOREAPP3_0 || NETCOREAPP3_1 || NET5_0) -#pragma warning disable IDE0051 // Remove unused private members - readonly object? syncRoot; -#pragma warning restore IDE0051 // Remove unused private members -#endif - public int Size; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static TSource[] GetItems(this List source) - => Unsafe.As, ListLayout>(ref source).Items!; - } -} diff --git a/NetFabric.Hyperlinq/Utils/MemoryPoolExtensions.cs b/NetFabric.Hyperlinq/Utils/MemoryPoolExtensions.cs deleted file mode 100644 index 795a7c317..000000000 --- a/NetFabric.Hyperlinq/Utils/MemoryPoolExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Buffers; -using System.Runtime.CompilerServices; - -namespace NetFabric.Hyperlinq -{ - static class MemoryPoolExtensions - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IMemoryOwner RentSliced(this MemoryPool pool, int count) - // ReSharper disable once HeapView.ObjectAllocation.Evident - => new SlicedMemoryOwner(pool.Rent(count), count); - - sealed class SlicedMemoryOwner - : IMemoryOwner - { - readonly IMemoryOwner oversized; - readonly int count; - - public SlicedMemoryOwner(IMemoryOwner oversized, int count) - => (this.oversized, this.count) = (oversized, count); - - public Memory Memory - => oversized.Memory.Slice(0, count); - - public void Dispose() - => oversized.Dispose(); - } - } -} diff --git a/NetFabric.Hyperlinq.SourceGenerator/Utils/MethodSymbolExtensions.cs b/NetFabric.Hyperlinq/Utils/MethodSymbolExtensions.cs similarity index 85% rename from NetFabric.Hyperlinq.SourceGenerator/Utils/MethodSymbolExtensions.cs rename to NetFabric.Hyperlinq/Utils/MethodSymbolExtensions.cs index 925d1aba1..a04fe3d7e 100644 --- a/NetFabric.Hyperlinq.SourceGenerator/Utils/MethodSymbolExtensions.cs +++ b/NetFabric.Hyperlinq/Utils/MethodSymbolExtensions.cs @@ -13,7 +13,7 @@ struct MethodInfo public string Name { get; set; } public IReadOnlyList<(string Name, string Constraints, bool IsConcreteType)> TypeParameters { get; set; } public IReadOnlyList<(string Name, string Type, string? DefaultValue)> Parameters { get; set; } - public ImmutableArray<(string, string, bool)> GenericsMapping { get; set; } + public ImmutableArray GenericsMapping { get; set; } } static class MethodSymbolExtensions @@ -29,7 +29,7 @@ public static IEnumerable GetTypeParameterSymbols(this IMe } } - public static MethodInfo GetInfo(this IMethodSymbol method, Compilation compilation, int skip = default) + public static MethodInfo GetInfo(this IMethodSymbol method, CompilationContext context, int skip = default) { try { @@ -40,22 +40,31 @@ public static MethodInfo GetInfo(this IMethodSymbol method, Compilation compilat Name = method.Name, Parameters = method.Parameters .Skip(skip) - .Select(parameter => (parameter.Name, parameter.Type.ToDisplayString(), parameter.HasExplicitDefaultValue ? (parameter.ExplicitDefaultValue is null ? "default" : parameter.ExplicitDefaultValue.ToString()) : default)) + .Select(parameter => (parameter.Name, parameter.Type.ToDisplayString(), parameter.HasExplicitDefaultValue ? parameter.ExplicitDefaultValue is null ? "default" : ToDisplayString(parameter.ExplicitDefaultValue) : default)) .ToArray(), TypeParameters = method.ContainingType.TypeParameters.Concat(method.TypeParameters) .Select(parameter => (parameter.ToDisplayString(), parameter.AsConstraintsStrings().ToCommaSeparated(), false)) .ToArray(), - GenericsMapping = method.GetGenericsMappings(compilation), + GenericsMapping = method.GetGenericsMappings(context), }; } catch (Exception ex) { throw; } + + static string ToDisplayString(object? obj) + => obj switch + { + null => "", + true => "true", + false => "false", + _ => obj.ToString() + }; } - public static MethodInfo ApplyMappings(this MethodInfo method, ImmutableArray<(string, string, bool)> typeGenericsMapping) + public static MethodInfo ApplyMappings(this MethodInfo method, ImmutableArray typeGenericsMapping) { var genericsMapping = typeGenericsMapping.AddRange(method.GenericsMapping); if (genericsMapping.IsDefault) @@ -102,9 +111,9 @@ public static bool IsOverload(this MethodInfo method0, MethodInfo method1) // check if parameter type is defined by contraints var constraints0 = method0.TypeParameters.FirstOrDefault(typeParameter => type0 == typeParameter.Name).Constraints; var constraints1 = method1.TypeParameters.FirstOrDefault(typeParameter => type1 == typeParameter.Name).Constraints; - if (string.IsNullOrEmpty(constraints0)) + if (constraints0 is null or { Length: 0 }) { - if (!string.IsNullOrEmpty(constraints1)) + if (constraints1 is not null and { Length: not 0 }) return false; if (type0 != type1) @@ -112,7 +121,7 @@ public static bool IsOverload(this MethodInfo method0, MethodInfo method1) } else { - if (string.IsNullOrEmpty(constraints1)) + if (constraints1 is null or { Length: 0 }) return false; return constraints0 == constraints1; diff --git a/NetFabric.Hyperlinq.SourceGenerator/Utils/NamespaceSymbolExtensions.cs b/NetFabric.Hyperlinq/Utils/NamespaceSymbolExtensions.cs similarity index 100% rename from NetFabric.Hyperlinq.SourceGenerator/Utils/NamespaceSymbolExtensions.cs rename to NetFabric.Hyperlinq/Utils/NamespaceSymbolExtensions.cs diff --git a/NetFabric.Hyperlinq/Utils/SkipLocalsInitAttribute.cs b/NetFabric.Hyperlinq/Utils/SkipLocalsInitAttribute.cs new file mode 100644 index 000000000..8c193e3ce --- /dev/null +++ b/NetFabric.Hyperlinq/Utils/SkipLocalsInitAttribute.cs @@ -0,0 +1,21 @@ +#if !NET5_0_OR_GREATER + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Module + | AttributeTargets.Class + | AttributeTargets.Struct + | AttributeTargets.Interface + | AttributeTargets.Constructor + | AttributeTargets.Method + | AttributeTargets.Property + | AttributeTargets.Event, Inherited = false)] + public sealed class SkipLocalsInitAttribute : Attribute + { + public SkipLocalsInitAttribute() + { + } + } +} + +#endif \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Utils/StringExtensions.cs b/NetFabric.Hyperlinq/Utils/StringExtensions.cs new file mode 100644 index 000000000..a9f23efd7 --- /dev/null +++ b/NetFabric.Hyperlinq/Utils/StringExtensions.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + static class StringExtensions + { + public static string ToCommaSeparated(this string[] strings) + => string.Join(", ", strings); + + public static string ToCommaSeparated(this IEnumerable strings) + => string.Join(", ", strings); + + public static string ToCommaSeparated(this IReadOnlyList strings) + => strings.Count switch + { + 0 => string.Empty, + 1 => strings[0], + _ => AppendCommaSeparated(new StringBuilder(), strings).ToString(), + }; + + public static StringBuilder AppendCommaSeparated(this StringBuilder builder, IReadOnlyList strings) + { + return strings.Count switch + { + 0 => builder, + 1 => builder.Append(strings[0]), + _ => PerformAppendCommaSeparated(builder, strings), + }; + + static StringBuilder PerformAppendCommaSeparated(StringBuilder builder, IReadOnlyList strings) + { + _ = builder.Append(strings[0]); + for (var index = 1; index < strings.Count; index++) + { + _ = builder.Append(", ").Append(strings[index]); + } + return builder; + } + } + + public static string CommaSeparateIfNotNullOrEmpty(params string?[] args) + { + return args.Length switch + { + 0 => string.Empty, + 1 => args[0] switch + { + null or { Length: 0 } => string.Empty, + _ => args[0]! + }, + _ => Append(args) + }; + + static string Append(params string?[] args) + { + var builder = new StringBuilder(); + foreach (var arg in args) + { + if (arg is not null and { Length: not 0 }) + { + if (builder.Length is not 0) + _ = builder.Append(", "); + + _ = builder.Append(arg); + } + } + return builder.ToString(); + } + } + + public static string ApplyMappings(this string value, ImmutableArray genericsMapping, out bool isConcreteType) + { + var result = value; + isConcreteType = false; + if (!genericsMapping.IsDefault) + { + foreach (var mapping in genericsMapping.Reverse()) + { + if (value == mapping.From && mapping.IsType) + { + isConcreteType = true; + return value.Replace(mapping.From, mapping.To); + } + result = result.Replace(mapping.From, mapping.To); + } + } + return result; + } + } +} diff --git a/NetFabric.Hyperlinq/Utils/SymbolExtensions.cs b/NetFabric.Hyperlinq/Utils/SymbolExtensions.cs new file mode 100644 index 000000000..d06260964 --- /dev/null +++ b/NetFabric.Hyperlinq/Utils/SymbolExtensions.cs @@ -0,0 +1,80 @@ +using Microsoft.CodeAnalysis; +using System.Collections.Immutable; +using System.Linq; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + static class SymbolExtensions + { + public static bool IsPublic(this ISymbol typeSymbol) + => typeSymbol.DeclaredAccessibility == Accessibility.Public; + + public static ImmutableArray GetGenericsMappings(this ISymbol type, CompilationContext compilation) + { + var attributes = type.GetAttributes() + .Where(attribute => SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, compilation.GeneratorMappingAttribute)) + .Select(attribute => new GeneratorMappingAttribute( + (string)attribute.ConstructorArguments[0].Value!, + (string)attribute.ConstructorArguments[1].Value!, + (bool)attribute.ConstructorArguments[2].Value!)); + + return ImmutableArray.CreateRange(attributes); + } + + public static GeneratorBindingsAttribute? GetBindingsAttribute(this ISymbol type, CompilationContext compilation) + { + var attribute = type.GetAttributes() + .FirstOrDefault(attribute => SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, compilation.GeneratorBindingsAttribute)); + + return attribute switch + { + null => null, + _ => new GeneratorBindingsAttribute( + (string)attribute.ConstructorArguments[0].Value!, + (string)attribute.ConstructorArguments[1].Value!, + (string?)attribute.ConstructorArguments[2].Value, + (string?)attribute.ConstructorArguments[3].Value, + (string?)attribute.ConstructorArguments[4].Value, + (string?)attribute.ConstructorArguments[5].Value, + (string?)attribute.ConstructorArguments[6].Value) + }; + } + + public static GeneratorIgnoreAttribute? GetIgnoreAttribute(this ISymbol type, CompilationContext compilation) + { + var attribute = type.GetAttributes() + .FirstOrDefault(attribute => SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, compilation.GeneratorIgnoreAttribute)); + + return attribute switch + { + null => null, + _ => new GeneratorIgnoreAttribute((bool)attribute.ConstructorArguments[0].Value!) + }; + } + + + public static bool ShouldIgnore(this ISymbol symbol, CompilationContext context) + => symbol.GetIgnoreAttribute(context)?.Value ?? false; + + + public static bool ShouldNotIgnore(this ISymbol symbol, CompilationContext context) + { + var attribute = symbol.GetIgnoreAttribute(context); + return attribute switch + { + null => false, + _ => !attribute.Value + }; + } + + public static (bool, string, bool) IsMapped(this ISymbol type, ImmutableArray genericsMapping) + { + foreach (var mapping in genericsMapping) + { + if (type.Name == mapping.From) + return (true, mapping.To, mapping.IsType); + } + return default; + } + } +} diff --git a/NetFabric.Hyperlinq.SourceGenerator/Utils/TypeParameterSymbolExtensions.cs b/NetFabric.Hyperlinq/Utils/TypeParameterSymbolExtensions.cs similarity index 89% rename from NetFabric.Hyperlinq.SourceGenerator/Utils/TypeParameterSymbolExtensions.cs rename to NetFabric.Hyperlinq/Utils/TypeParameterSymbolExtensions.cs index 151c76e36..7d163a680 100644 --- a/NetFabric.Hyperlinq.SourceGenerator/Utils/TypeParameterSymbolExtensions.cs +++ b/NetFabric.Hyperlinq/Utils/TypeParameterSymbolExtensions.cs @@ -7,7 +7,7 @@ namespace NetFabric.Hyperlinq.SourceGenerator { static class TypeParameterSymbolExtensions { - public static IEnumerable AsConstraintsStrings(this ITypeParameterSymbol parameter, ImmutableArray<(string, string, bool)> genericsMapping = default) + public static IEnumerable AsConstraintsStrings(this ITypeParameterSymbol parameter, ImmutableArray genericsMapping = default) { if (parameter.HasConstructorConstraint) yield return "new"; diff --git a/NetFabric.Hyperlinq/Utils/TypeSymbolConversionComparer.cs b/NetFabric.Hyperlinq/Utils/TypeSymbolConversionComparer.cs new file mode 100644 index 000000000..f151d8a02 --- /dev/null +++ b/NetFabric.Hyperlinq/Utils/TypeSymbolConversionComparer.cs @@ -0,0 +1,24 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using System.Collections.Generic; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + public class TypeSymbolConversionComparer + : IEqualityComparer + { + readonly Compilation compilation; + + public TypeSymbolConversionComparer(Compilation compilation) + => this.compilation = compilation; + + public bool Equals(ITypeSymbol x, ITypeSymbol y) + => (x is INamedTypeSymbol { IsGenericType: true } + && y is INamedTypeSymbol { IsGenericType: true } + && compilation.ClassifyConversion(x.OriginalDefinition, y.OriginalDefinition).Exists) + || compilation.ClassifyConversion(x, y).Exists; + + public int GetHashCode(ITypeSymbol obj) + => SymbolEqualityComparer.Default.GetHashCode(obj); + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.SourceGenerator/Utils/TypeSymbolExtensions.cs b/NetFabric.Hyperlinq/Utils/TypeSymbolExtensions.cs similarity index 66% rename from NetFabric.Hyperlinq.SourceGenerator/Utils/TypeSymbolExtensions.cs rename to NetFabric.Hyperlinq/Utils/TypeSymbolExtensions.cs index 49066684a..171729f9f 100644 --- a/NetFabric.Hyperlinq.SourceGenerator/Utils/TypeSymbolExtensions.cs +++ b/NetFabric.Hyperlinq/Utils/TypeSymbolExtensions.cs @@ -17,6 +17,7 @@ public static IEnumerable GetAllInterfaces(this ITypeSymbol ty yield return (INamedTypeSymbol)typeSymbol; #pragma warning disable IDE0007 // Use implicit type + // ReSharper disable once SuggestVarOrType_SimpleTypes ITypeSymbol? currentTypeSymbol = typeSymbol; #pragma warning restore IDE0007 // Use implicit type do @@ -37,38 +38,25 @@ public static IEnumerable GetAllInterfaces(this ITypeSymbol ty } while (currentTypeSymbol is not null && currentTypeSymbol.SpecialType != SpecialType.System_Object); } - public static ImmutableArray<(string, string, bool)> GetGenericsMappings(this ISymbol type, Compilation compilation) - { - var mappingAttributeSymbol = compilation.GetTypeByMetadataName("NetFabric.Hyperlinq.GeneratorMappingAttribute"); - var mappings = type.GetAttributes() - .Where(attribute => SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, mappingAttributeSymbol)) - .Select(attribute => ( - (string)attribute.ConstructorArguments[0].Value!, - (string)attribute.ConstructorArguments[1].Value!, - (bool)attribute.ConstructorArguments[2].Value!)); - - return ImmutableArray.CreateRange(mappings); - } - - public static string ToDisplayString(this ITypeSymbol type, ImmutableArray<(string, string, bool)> genericsMapping) + public static string ToDisplayString(this ITypeSymbol type, ImmutableArray genericsMapping) => type.ToDisplayString().ApplyMappings(genericsMapping, out _); static IEnumerable GetTypeArguments(ITypeSymbol typeSymbol) { - if (typeSymbol is INamedTypeSymbol namedType && namedType.IsGenericType) + if (typeSymbol is INamedTypeSymbol {IsGenericType: true} namedType) { var typeArguments = namedType.TypeArguments; - for (var index = 0; index < typeArguments.Length; index++) + foreach (var typeArgument in typeArguments) { - var typeArgument = typeArguments[index]; if (typeArgument is ITypeParameterSymbol typeParameter) yield return typeParameter; } } } - static IEnumerable<(string Name, ITypeParameterSymbol TypeParameter)> MapTypeParameters(IEnumerable typeParameters, ImmutableArray<(string, string, bool)> genericsMapping) + static IEnumerable<(string Name, ITypeParameterSymbol TypeParameter)> MapTypeParameters(IEnumerable typeParameters, ImmutableArray genericsMapping) { + // ReSharper disable once HeapView.ObjectAllocation.Evident var set = new HashSet(); foreach (var typeParameter in typeParameters) @@ -90,21 +78,11 @@ static IEnumerable<(string Name, ITypeParameterSymbol TypeParameter)> MapTypePar } } - public static IEnumerable<(string Name, string Constraints)> MappedTypeArguments(this ITypeSymbol type, ImmutableArray<(string, string, bool)> genericsMapping) + public static IEnumerable<(string Name, string Constraints)> MappedTypeArguments(this ITypeSymbol type, ImmutableArray genericsMapping) { var methodParameters = GetTypeArguments(type); return MapTypeParameters(methodParameters, genericsMapping) .Select(typeArgument => (typeArgument.Name, typeArgument.TypeParameter.AsConstraintsStrings(genericsMapping).ToCommaSeparated())); } - - static (bool, string, bool) IsMapped(this ITypeSymbol type, ImmutableArray<(string, string, bool)> genericsMapping) - { - foreach (var (from, to, isConcreteType) in genericsMapping) - { - if (type.Name == from) - return (true, to, isConcreteType); - } - return default; - } } } diff --git a/NetFabric.Hyperlinq/ValueEnumerableType.cs b/NetFabric.Hyperlinq/ValueEnumerableType.cs new file mode 100644 index 000000000..28b79c1f2 --- /dev/null +++ b/NetFabric.Hyperlinq/ValueEnumerableType.cs @@ -0,0 +1,6 @@ +using System; + +namespace NetFabric.Hyperlinq.SourceGenerator +{ + record ValueEnumerableType(string Name, string EnumeratorType, string ItemType, bool IsCollection, bool IsList); +} diff --git a/NuGet.config b/NuGet.config index c10b6783c..33baf744e 100755 --- a/NuGet.config +++ b/NuGet.config @@ -1,4 +1,4 @@ - + @@ -9,8 +9,7 @@ - - - + + - \ No newline at end of file + diff --git a/README.md b/README.md index 14ea605be..ed0625676 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ This implementation **favors performance in detriment of assembly binary size** - [Reduced heap allocations](#reduced-heap-allocations) - [Benchmarks](#benchmarks) - [Usage](#usage) - - [Passing items by reference](#passing-items-by-reference) - [Value delegates](#value-delegates) - [Generation operations](#generation-operations) - [Method return types](#method-return-types) @@ -75,24 +74,23 @@ The names of the benchmarks are structured as follow: - The library used: - _Linq_ - the `System.Linq` namespace (includes [System.Linq.Async](https://www.nuget.org/packages/System.Linq.Async/), [System.Interactive](https://www.nuget.org/packages/System.Interactive/), and [System.Interactive.Async](https://www.nuget.org/packages/System.Interactive.Async/)) - _StructLinq_ - [StructLinq](https://www.nuget.org/packages/StructLinq/) - - _Hyperlinq_ - [NetFabric.Hyperlinq](https://www.nuget.org/packages/Hyperlinq/) + - _Hyperlinq_ - [NetFabric.Hyperlinq](https://www.nuget.org/packages/NetFabric.Hyperlinq/) - The type of collection used as source: - _Array_ - an array - _Span_ - a `Span<>` - _Memory_ - a `Memory<>` - _Enumerable_ - implements `IEnumerable<>` - _Collection_ - implements `IReadOnlyCollection<>` and `ICollection<>` - - _List_ - implements `IReadOnlyList<>` and `IList<>` but not an array + - _List_ - implements `IReadOnlyList<>` and `IList<>` but is not an array - _AsyncEnumerable_ - implements `IAsyncEnumerable<>` - The type of enumerator provided by the source: - _Value_ - the enumerator is a value type - _Reference_ - the enumerator is a reference type -- The contents of the source: - - _Sequential_ - contains numbers in sequential order - - _Random_ - contains numbers in random order - How the result of the operation is iterated: - _For_ - a `for` loop is used to call the indexer - - _Foreach_ - a `foreach` loop is used to call the enumerator + - _Foreach_ - a `foreach` loop is used to call the enumerator +- Has a variant: + - _SIMD_ - using SIMD ## Usage @@ -107,7 +105,7 @@ using System.Linq; using NetFabric.Hyperlinq; // add this directive ``` -- Use the methods `AsValueEnumerable()`or `AsAsyncValueEnumerable()` to make any collection usable with `NetFabric.Hyperlinq`. This includes arrays, `Memory<>`, `ReadOnlyMemory<>`, BCL collections, and any other implementation of `IEnumerable<>` or `IAsyncEnumerable<>`. It's not required for `Span<>` and `ReadOnlySpan<>`. +- Use the methods `AsValueEnumerable()` to make any collection usable with `NetFabric.Hyperlinq`. This includes arrays, `Memory<>`, `ReadOnlyMemory<>`, `Span<>`, `ReadOnlySpan<>`, BCL collections, and any other implementation of `IEnumerable<>`. Use `AsAsyncValueEnumerable()` for any implementation of `IAsyncEnumerable<>`. ``` csharp public static void Example(IReadOnlyList list) @@ -122,9 +120,11 @@ public static void Example(IReadOnlyList list) } ``` -- All enumerables returned by `NetFabric.Hyperlinq` are compatible with `System.Linq`. +- `Netfabric.Hyperlinq` contains special versions of `AsValueEnumerable()` for better performance with all collections in the `System.Collections.Immutable` namespace. Projects targetting .NET Framework, `netcoreapp2.1` or `netstandard2.0`, require the addition of the [`NetFabric.Hyperlinq.Immutable` NuGet package](https://www.nuget.org/packages/NetFabric.Hyperlinq.Immutable/) dependency. -`OrderByDescending()` is not yet available in `Netfabric.Hyperlinq` but can still be used without requiring any conversion: +- Most enumerables returned by `NetFabric.Hyperlinq` are compatible with `System.Linq`. The exception is enumerables for `Span<>` or `ReadOnlySpan<>`. + +This allows the use of `System.Linq` operators on `NetFabric.Hyperlinq` enumerables. `OrderByDescending()` is not yet available in `Netfabric.Hyperlinq` but can still be used without requiring any conversion: ``` csharp public static void Example(IReadOnlyList list) @@ -143,65 +143,53 @@ public static void Example(IReadOnlyList list) To add `NetFabric.Hyperlinq` operations after a `System.Linq` operation, simply add one more `AsValueEnumerable()` or `AsAsyncValueEnumerable()`. -### Passing items by reference - -`NetFabric.Hyperlinq` supports passing the items by reference. This can improve considerably the performance for large structures. - -- Use `AsValueEnumerableRef()` instead to make any collection usable with `NetFabric.Hyperlinq`. -- Declare the lambda expressions with `in` keyword on the first parameter. This also requires the declaration of the parameters' type. - -``` csharp -public static void Example(IReadOnlyList list) -{ - var result = list - .AsValueEnumerable() - .Where((in int item) => item > 2) - .Select((in int item) => item * 2); - - foreach(var value in result) - Console.WriteLine(value); -} -``` - ### Value delegates -Calling a lambda expression for each item of the collection is very expensive. `NetFabric.Hyperlinq` supports a much more performant alternative. +Calling a lambda expression for each item of the collection is very expensive. `NetFabric.Hyperlinq` supports an alternative that is not as practical but that has much better performance. -- Declare a `struct` that implements `IFunction<>` or `IFunctionIn<>`. +- Declare a `struct` that implements `IFunction<>`. Here's two examples of how to implement: ``` csharp -readonly struct DoubleOfInt32 +readonly struct MultiplyBy2 : IFunction { public int Invoke(int element) => element * 2; } -readonly struct DoubleOfInt32ByRef - : IFunctionIn +readonly struct LessThan + : IFunction { - public int Invoke(in int element) - => element * 2; + readonly int value; + + public LessThan(int value) + => this.value = value; + + public bool Invoke(int element) + => element < value; } ``` -- Add the name of the structure to the method generics arguments +- Pass an instance as a parameter or just add the type to the generics arguments list (uses the default constructor): ``` csharp public static void Example(IReadOnlyList list) { var result = list .AsValueEnumerable() - .Select(); + .Where(new LessThan(10)) + .Select(); foreach(var value in result) Console.WriteLine(value); } ``` +The instances are allocated on the stack and the methods calls are non-virtual. + ### Generation operations -In `NetFabric.Hyperlinq`, the generation operations like `Empty()`, `Range()`, `Repeat()` and `Return()` are static methods implemented in the static class `ValueEnumerable`. To use the equivalent operations from `NetFabric.Hyperlinq`, simply replace `Enumerable` for `ValueEnumerable`. +In `NetFabric.Hyperlinq`, the generation operations like `Empty()`, `Range()`, `Repeat()` and `Return()` are static methods implemented in the static class `ValueEnumerable`. To use them, instead of the `System.Linq` equivalents, simply use `ValueEnumerable` instead of `Enumerable`. ``` csharp public static void Example(int count) @@ -215,54 +203,6 @@ public static void Example(int count) } ``` -### Method return types - -Usually, when returning a query, it's used `IEnumerable<>` as the method return type: - -``` csharp -public static IEnumerable Example(int count) - => ValueEnumerable - .Range(0, count) - .Select(value => value * 2); -``` - -This allows the caller to use `System.Linq` or a `foreach` loop to pull and process the result. `NetFabric.Hyperlinq` can also be used but the `AsValueEnumerable()` conversion method has to be used. - -The operation in `NetFabric.Hyperlinq` are implemented so that they return the highest level enumeration interface possible. For example, the `Range()` operation return implements `IValueReadOnlyList<,>` and the subsequent `Select()` return does the same thing. `IValueReadOnlyList<,>` derives from `IReadOnlyList<>` so, we can change the method to return this interface: - -``` csharp -public static IReadOnlyList Example(int count) - => ValueEnumerable - .Range(0, count) - .Select(value => value * 2); -``` - -Now, the caller is free to use the enumerator or the indexer, which are provided by this interface. This means that, all previous methods of iteration can be used plus the `for` loops, which is much more efficient. The indexer performs fewer internal operations and doesn't need an enumerator instance. `NetFabric.Hyperlinq` can also be used and the `AsValueEnumerable()` conversion method still has to be used but, `NetFabric.Hyperlinq` will now use the indexer. - -Otherwise, `NetFabric.Hyperlinq` will use enumerators. It implements all enumerators as value types. This allows the enumerators not to be allocated on the heap and calls to its methods to be non-virtual. The `IEnumerable<>` interface, and all other derived BCL interfaces, convert the enumerator to the `IEnumerator<>` interface. This results in the enumerator to be boxed, undoing the mentioned benefits. - -`NetFabric.Hyperlinq` defines enumerable interfaces that contain the enumerator type as a generic parameter. This allows the caller to use it without boxing. Consider changing the method to return one of these interfaces: - -``` csharp -public static IValueReadOnlyList.DisposableEnumerator> Example(int count) - => ValueEnumerable - .Range(0, count) - .Select(value => value * 2); -``` - -The caller is now able to use `NetFabric.Hyperlinq` without requiring the `AsValueEnumerable()` conversion method. In this case, it will use the indexer in all subsequent operations but the enumerator is still available. In other cases (`IValueEnumerable<,>`, `IValueReadOnlyCollection<,>` and `IAsyncValueEnumerable<,>`) it will use the enumerator. - -`NetFabric.Hyperlinq` also implements the enumerables as value types. Returning an interface means that the enumerable will still be boxed. If you want to also avoid this, consider changing the return type to be the actual enumerable type. In this case: - -``` csharp -public static ReadOnlyList.SelectEnumerable Example(int count) - => ValueEnumerable - .Range(0, count) - .Select(value => value * 2); -``` - -**NOTE:** Returning the enumerable type or a value enumeration interface, allows major performance improvements but creates a library design issue. Changes in the method implementation may result in changes to the retun type. This is a breaking change. This is an issue on the public API but not so much for the private and internal methods. Take this into consideration when deciding on the return type. - ### Composition `NetFabric.Hyperlinq` operations can be composed just like with `System.Linq`. The difference is on how each one optimizes the internals to reduce the number of enumerators required to iterate the values. @@ -275,17 +215,7 @@ var result = source.AsValueEnumerable() .Select(item => item * 2); ``` -But, `System.Linq` does not do the same for this other example: - -``` csharp -var result = source.AsValueEnumerable() - .Where(item => item > 2) - .First(); -``` - -`System.Linq` has a second overload for methods, like `First()` and `Single()`, that take the predicate as a parameter and allow the `Where()` to be removed. In `NetFabric.Hyperlinq` this is not required. With the intention of reducing the code to be maintained and tested, these other overloads actually are not available in `NetFabric.Hyperlinq`. - -`NetFabric.Hyperlinq` includes many more composition optimizations. In the following code, only one enumerator is used, and only because of the `Where()` operation. Otherwise, the indexer would have been used instead. Also, the `Select()` is applied after `First()`, so that it's applied to only to the resulting item: +`NetFabric.Hyperlinq` includes many more composition optimizations. In the following code, only one enumerator is used: ``` csharp var result = array.AsValueEnumerable() @@ -298,7 +228,7 @@ var result = array.AsValueEnumerable() ### Option -In `System.Linq`, the aggregation operations like `First()`, `Single()` and `ElementAt()`, throw an exception when the source has no items. Often, empty collections are a valid scenario and exception handling is very slow. `System.Linq` has alternative methods like `FirstOrDefault()`, `SingleOrDefault()` and `ElementAtOrDefault()`, that return the `default` value instead of throwing. This is still an issue when the items are value-typed, where there's no way to distinguish between an empty collection and a valid item. +In `System.Linq`, the aggregation operations like `First()`, `Single()` and `ElementAt()`, throw an exception when the source has no items. Often, empty collections are a valid scenario and exception handling is very slow. `System.Linq` has alternative methods like `FirstOrDefault()`, `SingleOrDefault()` and `ElementAtOrDefault()`, that return the `default` value instead of throwing. This is still an issue when the items are of a value-type, where there's no way to distinguish between an empty collection and a valid item. In `NetFabric.Hyperlinq`, aggregation operations return an `Option<>` type. This is similar in behavior to the [`Nullable<>`](https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1) but it can contain reference types. @@ -321,13 +251,17 @@ if (isSome) If you prefer a more functional approach, you can use `Match()` to specify the value returned when the collection has values and when it's empty. Here's how to use it to define the previous behavior of `First()` and `FirstOrDefault()`: ``` csharp -var first = source.AsValueEnumerable().First().Match( - item => item, - () => throw new InvalidOperationException("Sequence contains no elements")); - -var firstOrDefault = source.AsValueEnumerable().First().Match( - item => item, - () => default); +var first = source.AsValueEnumerable() + .First() + .Match( + item => item, + () => throw new InvalidOperationException("Sequence contains no elements")); + +var firstOrDefault = source.AsValueEnumerable() + .First() + .Match( + item => item, + () => default); Console.WriteLine(first); Console.WriteLine(firstOrDefault); @@ -336,45 +270,49 @@ Console.WriteLine(firstOrDefault); `Match()` can also be used to define actions: ``` csharp -source.AsValueEnumerable().First().Match( - item => Console.WriteLine(item), - () => { }); +source.AsValueEnumerable() + .First() + .Match( + item => Console.WriteLine(item), + () => { }); ``` The `NetFabric.Hyperlinq` operations can be applied to `Option<>`, including `Where()`, `Select()` and `SelectMany()`. These return another `Option<>` with the predicate/selector applied to the value, if it exists. ```csharp -source.AsValueEnumerable().First().Where(item => item > 2).Match( - item => Console.WriteLine(item), - () => { }); +source.AsValueEnumerable() + .First() + .Where(item => item > 2) + .Match( + item => Console.WriteLine(item), + () => { }); ``` ### Buffer pools -[Buffer pools](https://adamsitnik.com/Array-Pool/) allow the use of heap memory without adding pressure to the garbage collector. It preallocates a chunk of memory and "rents" it as required. The garbage collector will add this memory to the Large Object Heap (LOH). +[Buffer pools](https://adamsitnik.com/Array-Pool/) allow the use of heap memory without adding pressure to the garbage collector. It pre-allocates a chunk of memory and "rents" it as required. The garbage collector will add this memory to the Large Object Heap (LOH). -`ToArray()` is usually used to cache values for a brief period. `Netfabric.Hyperlinq` adds an oveload that takes a `MemoryPool<>` as a parameter: +`ToArray()` is frequently used to cache values for a brief period and the use of buffer pools may be useful. + +`Netfabric.Hyperlinq` adds an overload that takes a `ArrayPool<>` as a parameter: ``` csharp -using var buffer = source.AsValueEnumerable() - .ToArray(MemoryPool.Shared); -var memory = buffer.Memory; -// use memory here +void Method() +{ + using var buffer = source.AsValueEnumerable() + .ToArray(ArrayPool.Shared); + var memory = buffer.Memory; + // use memory here +} ``` -It returns an [`IMemoryOwner<>`](https://docs.microsoft.com/en-us/dotnet/api/system.buffers.imemoryowner-1). The `using` statement guarantees that it is disposed and the buffer automatically returned to the pool. +It returns an instance of a [`IMemoryOwner<>`](https://docs.microsoft.com/en-us/dotnet/api/system.buffers.imemoryowner-1). The `using` statement guarantees that it is disposed and the buffer automatically returned to the pool. ### SIMD -`NetFabric.Hyperlinq` uses SIMD implicitly to improve performance when possible, but many times it can only be done explicitly by calling specific operations. - -SIMD improves performance by performing the same operations simultaneously on multiple items. The operation can only be performed if this number is met. This means that a remaining number of items has to be processed without SIMD. +`NetFabric.Hyperlinq` uses SIMD implicitly to improve performance of some operations. Many times this can only be done explicitly because it can only be used on a limited number of types and operations on them. -The items processed simultaneously are stored inside a [`System.Numerics.Vector`](https://docs.microsoft.com/en-us/dotnet/api/system.numerics.vector-1) structure. - -Operations that require an expression to process data, on the SIMD-enable equivalent require an expression that applies it at the [`System.Numerics.Vector`](https://docs.microsoft.com/en-us/dotnet/api/system.numerics.vector-1) level and another one at the item level. - -For this reason, and also because SIMD cannot be applied to all data types, SIMD specific operations have be called. The method has a `Vector` post-fix in the name. +In `NetFabric.Hyperlinq`, alternative methods that use SIMD, have the word `Vector` at the end of its name. You'll also find that the operations that require an expression, now require two. ``` csharp var result = list @@ -383,10 +321,12 @@ var result = list .ToArray(); ``` -These methods also support value delegates. In this case, the `struct` containing the expressions must implement two `IFunction<,>`. +SIMD improves performance by performing the same operations simultaneously on multiple items. The operation can only be performed if this number is met. This means that the remaining number of items has to be processed without SIMD. The first expression is applied on a [`System.Numerics.Vector<>`](https://docs.microsoft.com/en-us/dotnet/api/system.numerics.vector-1), while the second one is applied on an item. + +These methods also support the use of [value delegates](#value-delegates). In this case, the `struct` containing the expressions must implement two `IFunction<,>`: ``` csharp -readonly struct DoubleOfInt32 +readonly struct MultiplyBy2 : IFunction, Vector> , IFunction { @@ -401,7 +341,7 @@ public static void Example(List list) { var result = list .AsValueEnumerable() - .SelectVector() + .SelectVector() .ToArray(); foreach(var value in result) @@ -409,7 +349,7 @@ public static void Example(List list) } ``` -Please note that the operation `SelectVector()` does not return and enumerable. It returns the context required for subsequent operations like `ToArray()`, `ToList()`, and `Sum()`. +Please note that the operation `SelectVector()` does not return an enumerable. It returns the context required for subsequent operations like `ToArray()`, `ToList()`, and `Sum()`. Up until now I haven't found a way to improve the performance of `Select()` by using SIMD. The returned context allows the use of composition, exposing only the operations that can gain with the use of SIMD. @@ -486,6 +426,7 @@ The following open-source projects are used to build and test this project: - [.NET](https://github.com/dotnet) - [BenchmarkDotNet](https://benchmarkdotnet.org/) +- [Ben.TypeDictionary](https://github.com/benaadams/Ben.TypeDictionary) - [coveralls](https://coveralls.io) - [coverlet](https://github.com/tonerdo/coverlet) - [ILRepack](https://github.com/gluck/il-repack) @@ -494,6 +435,7 @@ The following open-source projects are used to build and test this project: - [NetFabric.Hyperlinq.Analyzer](https://github.com/NetFabric/NetFabric.Hyperlinq.Analyzer) - [Nullable](https://github.com/manuelroemer/Nullable) - [Source Link](https://github.com/dotnet/sourcelink) +- [UnoptimizedAssemblyDetector](https://github.com/bruno-garcia/unoptimized-assembly-detector) - [xUnit.net](https://xunit.net/) ## License