diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0cc4457c..1b506bc5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,7 +65,7 @@ jobs: - uses: actions/setup-dotnet@v3 name: Install Current .NET SDK - name: Generate NuGet Packages - run: dotnet pack --configuration Release --output nupkg /p:FunckyBuildWithPreviewTargetFramework=false + run: dotnet pack --output nupkg - uses: actions/upload-artifact@v3 if: success() && github.ref == 'refs/heads/main' with: diff --git a/.github/workflows/publish-nightly-package.yml b/.github/workflows/publish-nightly-package.yml index 54de91e6..7d36db7b 100644 --- a/.github/workflows/publish-nightly-package.yml +++ b/.github/workflows/publish-nightly-package.yml @@ -13,6 +13,6 @@ jobs: - uses: actions/setup-dotnet@v3 name: Install Current .NET SDK - name: Pack Packages - run: dotnet pack Funcky/Funcky.csproj --configuration Release --output nupkg --version-suffix "nightly.$(git rev-parse --short "${{github.sha}}")" /p:GeneratePackageOnBuild=false + run: dotnet pack Funcky/Funcky.csproj --output nupkg --version-suffix "nightly.$(git rev-parse --short "${{github.sha}}")" - name: Push Package run: dotnet nuget push --source https://nuget.pkg.github.com/polyadic/index.json --api-key ${{secrets.GITHUB_TOKEN}} nupkg/Funcky.*.nupkg diff --git a/Directory.Build.props b/Directory.Build.props index cd74e938..3b750436 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -26,9 +26,6 @@ - - true - $(MSBuildThisFileDirectory)artifacts diff --git a/FrameworkFeatureConstants.props b/FrameworkFeatureConstants.props index cd17d346..15a19520 100644 --- a/FrameworkFeatureConstants.props +++ b/FrameworkFeatureConstants.props @@ -16,6 +16,6 @@ $(DefineConstants);GENERIC_MATH;GENERIC_PARSEABLE - $(DefineConstants);RANDOM_SHUFFLE + $(DefineConstants);RANDOM_SHUFFLE;UTF8_SPAN_PARSEABLE diff --git a/Funcky.Async/Funcky.Async.csproj b/Funcky.Async/Funcky.Async.csproj index da8da973..631d1813 100644 --- a/Funcky.Async/Funcky.Async.csproj +++ b/Funcky.Async/Funcky.Async.csproj @@ -1,7 +1,6 @@ - net5.0;netstandard2.1;netstandard2.0 - net8.0;$(TargetFrameworks) + net8.0;net5.0;netstandard2.1;netstandard2.0 preview enable Extends Funcky with support for IAsyncEnumerable and Tasks. @@ -20,9 +19,7 @@ Funcky $(DefineConstants);CONTRACTS_FULL - - + true true diff --git a/Funcky.Test/Extensions/EnumerableExtensions/AnyOrElseTest.cs b/Funcky.Test/Extensions/EnumerableExtensions/AnyOrElseTest.cs index a2e2ff9e..53d1c71a 100644 --- a/Funcky.Test/Extensions/EnumerableExtensions/AnyOrElseTest.cs +++ b/Funcky.Test/Extensions/EnumerableExtensions/AnyOrElseTest.cs @@ -13,7 +13,7 @@ public void IsEmptyWhenBothEnumerablesAreEmpty() [Fact] public void IsSourceEnumerableWhenNonEmpty() { - var source = Sequence.Return(1, 2, 3).EraseNonEnumeratedCount(); + var source = Sequence.Return(1, 2, 3).PreventLinqOptimizations(); var fallback = Sequence.Return(4, 5, 6); Assert.Equal(source, source.AnyOrElse(fallback)); } @@ -21,7 +21,7 @@ public void IsSourceEnumerableWhenNonEmpty() [Fact] public void IsFallbackEnumerableWhenSourceIsEmpty() { - var source = Enumerable.Empty().EraseNonEnumeratedCount(); + var source = Enumerable.Empty().PreventLinqOptimizations(); var fallback = Sequence.Return(1, 2, 3); Assert.Equal(fallback, source.AnyOrElse(fallback)); } @@ -36,7 +36,7 @@ public void SourceIsEnumeratedLazily() [Fact] public void FallbackIsEnumeratedLazily() { - var source = Enumerable.Empty().EraseNonEnumeratedCount(); + var source = Enumerable.Empty().PreventLinqOptimizations(); _ = source.AnyOrElse(new FailOnEnumerationSequence()); } diff --git a/Funcky.Test/Extensions/EnumerableExtensions/GetNonEnumeratedCountOrNoneTest.cs b/Funcky.Test/Extensions/EnumerableExtensions/GetNonEnumeratedCountOrNoneTest.cs index 54bef9df..2b6e1097 100644 --- a/Funcky.Test/Extensions/EnumerableExtensions/GetNonEnumeratedCountOrNoneTest.cs +++ b/Funcky.Test/Extensions/EnumerableExtensions/GetNonEnumeratedCountOrNoneTest.cs @@ -28,7 +28,7 @@ public void GetNonEnumeratedCountOrNoneReturnsCountOnEnumerableRange() [Property] public Property GetNonEnumeratedCountOrNoneReturnsNoneForInstancesWithoutCount(List list) { - return list.EraseNonEnumeratedCount().GetNonEnumeratedCountOrNone() + return list.PreventLinqOptimizations().GetNonEnumeratedCountOrNone() .Match(none: true, some: False) .ToProperty(); } diff --git a/Funcky.Test/Extensions/EnumerableExtensions/MaterializeTest.cs b/Funcky.Test/Extensions/EnumerableExtensions/MaterializeTest.cs index 5b9fcd73..1135d1bc 100644 --- a/Funcky.Test/Extensions/EnumerableExtensions/MaterializeTest.cs +++ b/Funcky.Test/Extensions/EnumerableExtensions/MaterializeTest.cs @@ -26,7 +26,7 @@ public void MaterializeDoesNotEnumerateCollectionTypes() [Fact] public void MaterializeReturnsImmutableCollectionWhenEnumerated() { - var sequence = Enumerable.Repeat("Hello world!", 3); + var sequence = Enumerable.Repeat("Hello world!", 3).PreventLinqOptimizations(); Assert.IsType>(sequence.Materialize()); } @@ -34,11 +34,22 @@ public void MaterializeReturnsImmutableCollectionWhenEnumerated() [Fact] public void MaterializeWithMaterializationReturnsCorrectCollectionWhenEnumerate() { - var sequence = Enumerable.Repeat("Hello world!", 3); + var sequence = Enumerable.Repeat("Hello world!", 3).PreventLinqOptimizations(); Assert.IsType>(sequence.Materialize(ToHashSet)); } +#if NET8_0_OR_GREATER + // This is an optimization added in .NET 8 + [Fact] + public void MaterializeDoesNotEnumerableEnumerableReturnedByRepeat() + { + var sequence = Enumerable.Repeat("Hello world!", 3); + var materialized = sequence.Materialize>(_ => throw new FailException("Materialization should never be called")); + Assert.Same(sequence, materialized); + } +#endif + [Fact] public void MaterializeDoesNotEnumerateCollectionWhichImplementsICollectionOnly() { diff --git a/Funcky.Test/TestUtils/EnumerableExtensions.cs b/Funcky.Test/TestUtils/EnumerableExtensions.cs index 97873c08..33b78295 100644 --- a/Funcky.Test/TestUtils/EnumerableExtensions.cs +++ b/Funcky.Test/TestUtils/EnumerableExtensions.cs @@ -2,10 +2,9 @@ namespace Funcky.Test.TestUtils; internal static class EnumerableExtensions { - internal static IEnumerable EraseNonEnumeratedCount(this IEnumerable source) + /// Prevents LINQ from optimizing by hiding the underlying source enumerable. + internal static IEnumerable PreventLinqOptimizations(this IEnumerable source) { - // Having our own state machine erases the non enumerated count - // provided when using LINQ methods such as Select. foreach (var element in source) { yield return element; diff --git a/Funcky/CompatibilitySuppressions.xml b/Funcky/CompatibilitySuppressions.xml new file mode 100644 index 00000000..96b033ac --- /dev/null +++ b/Funcky/CompatibilitySuppressions.xml @@ -0,0 +1,10 @@ + + + + + CP0002 + M:Funcky.Extensions.EnumerableExtensions.Chunk``1(System.Collections.Generic.IEnumerable{``0},System.Int32) + lib/net5.0/Funcky.dll + lib/net6.0/Funcky.dll + + \ No newline at end of file diff --git a/Funcky/Extensions/ParseExtensions/ParseExtensions.GenericParseable.cs b/Funcky/Extensions/ParseExtensions/ParseExtensions.GenericParseable.cs index d8cb3572..63a370da 100644 --- a/Funcky/Extensions/ParseExtensions/ParseExtensions.GenericParseable.cs +++ b/Funcky/Extensions/ParseExtensions/ParseExtensions.GenericParseable.cs @@ -1,8 +1,8 @@ -#if GENERIC_PARSEABLE namespace Funcky.Extensions; public static partial class ParseExtensions { +#if GENERIC_PARSEABLE public static Option ParseOrNone(this ReadOnlySpan value, IFormatProvider? provider) where TParseable : ISpanParsable => TParseable.TryParse(value, provider, out var result) @@ -14,5 +14,13 @@ public static Option ParseOrNone(this string? value, IFo => TParseable.TryParse(value, provider, out var result) ? result : Option.None; -} #endif + +#if UTF8_SPAN_PARSEABLE + public static Option ParseOrNone(this ReadOnlySpan utf8Text, IFormatProvider? provider) + where TParseable : IUtf8SpanParsable + => TParseable.TryParse(utf8Text, provider, out var result) + ? result + : Option.None; +#endif +} diff --git a/Funcky/Funcky.csproj b/Funcky/Funcky.csproj index e9972412..5dd037d6 100644 --- a/Funcky/Funcky.csproj +++ b/Funcky/Funcky.csproj @@ -1,7 +1,6 @@ - net7.0;net6.0;net5.0;netcoreapp3.1;netstandard2.0;netstandard2.1 - net8.0;$(TargetFrameworks) + net8.0;net7.0;net6.0;net5.0;netcoreapp3.1;netstandard2.0;netstandard2.1 preview enable Funcky @@ -19,7 +18,7 @@ $(DefineConstants);CONTRACTS_FULL - net7.0 + net8.0 @@ -39,9 +38,7 @@ - - + true true diff --git a/Funcky/PublicAPI.Unshipped.txt b/Funcky/PublicAPI.Unshipped.txt index d75c8b9c..7c28104c 100644 --- a/Funcky/PublicAPI.Unshipped.txt +++ b/Funcky/PublicAPI.Unshipped.txt @@ -11,10 +11,44 @@ Funcky.Monads.Result.OrElse(Funcky.Monads.Result fal Funcky.Monads.Result.OrElse(System.Func>! fallback) -> Funcky.Monads.Result Funcky.UpCast static Funcky.Extensions.EnumeratorExtensions.MoveNextOrNone(this System.Collections.Generic.IEnumerator! enumerator) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseByteOrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseByteOrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseByteOrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseDecimalOrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseDecimalOrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseDecimalOrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseDoubleOrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseDoubleOrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseDoubleOrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseInt16OrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseInt16OrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseInt16OrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseInt32OrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseInt32OrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseInt32OrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseInt64OrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseInt64OrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseInt64OrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option static Funcky.Extensions.ParseExtensions.ParseNumberOrNone(this string! value, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option static Funcky.Extensions.ParseExtensions.ParseNumberOrNone(this System.ReadOnlySpan value, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option static Funcky.Extensions.ParseExtensions.ParseOrNone(this string? value, System.IFormatProvider? provider) -> Funcky.Monads.Option static Funcky.Extensions.ParseExtensions.ParseOrNone(this System.ReadOnlySpan value, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseOrNone(this System.ReadOnlySpan utf8Text, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseSByteOrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseSByteOrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseSByteOrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseSingleOrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseSingleOrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseSingleOrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseUInt16OrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseUInt16OrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseUInt16OrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseUInt32OrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseUInt32OrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseUInt32OrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseUInt64OrNone(this System.ReadOnlySpan candidate, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseUInt64OrNone(this System.ReadOnlySpan candidate, System.IFormatProvider? provider) -> Funcky.Monads.Option +static Funcky.Extensions.ParseExtensions.ParseUInt64OrNone(this System.ReadOnlySpan candidate) -> Funcky.Monads.Option static Funcky.Extensions.StringExtensions.Chunk(this string! source, int size) -> System.Collections.Generic.IEnumerable! static Funcky.Extensions.StringExtensions.SlidingWindow(this string! source, int width) -> System.Collections.Generic.IEnumerable! static Funcky.UpCast.From(System.Lazy! lazy) -> System.Lazy! diff --git a/global.json b/global.json index 5d540d5e..3f809cbf 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100-preview.5.23303.2", + "version": "8.0.100", "rollForward": "feature" } }