Skip to content

Commit

Permalink
Merge pull request #745 from polyadic/generic-parse-or-none
Browse files Browse the repository at this point in the history
Implement Generic ParseOrNone extensions.
  • Loading branch information
FreeApophis authored Sep 22, 2023
2 parents 79d8f9b + 0366510 commit 3ebf182
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 4 deletions.
3 changes: 3 additions & 0 deletions FrameworkFeatureConstants.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0' Or '$(TargetFramework)' == 'net7.0' Or '$(TargetFramework)' == 'net8.0'">
<DefineConstants>$(DefineConstants);STACK_TRACE_HIDDEN_SUPPORTED;DATE_ONLY_SUPPORTED;TIME_ONLY_SUPPORTED;PRIORITY_QUEUE;TRY_GET_NON_ENUMERATED_COUNT;HTTP_HEADERS_NON_VALIDATED;ELEMENT_AT_INDEX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net7.0' Or '$(TargetFramework)' == 'net8.0'">
<DefineConstants>$(DefineConstants);GENERIC_MATH;GENERIC_PARSEABLE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
<DefineConstants>$(DefineConstants);RANDOM_SHUFFLE</DefineConstants>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#if GENERIC_PARSEABLE
using System.Globalization;

namespace Funcky.Test.Extensions.ParseExtensions;

public sealed partial class ParseExtensionsTest
{
[Theory]
[MemberData(nameof(ParseableDoubleNumbers))]
public void ParseGenericStringReturnsTheExpectedDouble(Option<double> expected, string input)
{
Assert.Equal(expected, input.ParseNumberOrNone<double>(NumberStyles.Number, null));
Assert.Equal(expected, input.ParseOrNone<double>(null));
}

[Theory]
[MemberData(nameof(ParseableDoubleNumbers))]
public void ParseGenericSpanReturnsTheExpectedDouble(Option<double> expected, string input)
{
Assert.Equal(expected, input.AsSpan().ParseNumberOrNone<double>(NumberStyles.Number, null));
Assert.Equal(expected, input.AsSpan().ParseOrNone<double>(null));
}

public static TheoryData<Option<double>, string> ParseableDoubleNumbers()
=> new()
{
{ Option.Some(1.0), "1.0" },
{ Option.Some(3.145), "3.145" },
{ Option.Some(0.5), ".5" },
{ Option.Some(1.0), "1.0" },
{ Option.Some(42.0), "42" },
{ Option<double>.None, string.Empty },
{ Option<double>.None, "no-number" },
};
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public void ParseVersionIsTheSameAsTryParseForValidVersions(string input)
FunctionalAssert.Some(expected!, input.ParseVersionOrNone());
}

#if PARSE_READ_ONLY_SPAN_SUPPORTED
#if PARSE_READ_ONLY_SPAN_SUPPORTED
[Theory]
[InlineData("1.0")]
[InlineData("1.0.0")]
Expand All @@ -26,7 +26,7 @@ public void ParseVersionIsTheSameAsTryParseForValidVersionsWithReadOnlySpan(stri
Assert.True(Version.TryParse(inputSpan, out var expected));
FunctionalAssert.Some(expected!, inputSpan.ParseVersionOrNone());
}
#endif
#endif

[Property]
public Property ParseVersionIsTheSameAsTryParse(string input)
Expand All @@ -38,7 +38,7 @@ public Property ParseVersionIsTheSameAsTryParse(string input)
return result.ToProperty();
}

#if PARSE_READ_ONLY_SPAN_SUPPORTED
#if PARSE_READ_ONLY_SPAN_SUPPORTED
[Property]
public Property ParseVersionIsTheSameAsTryParseWithReadOnlySpan(string input)
{
Expand All @@ -49,5 +49,5 @@ public Property ParseVersionIsTheSameAsTryParseWithReadOnlySpan(string input)
: parsed.Match(none: true, some: False);
return result.ToProperty();
}
#endif
#endif
}
20 changes: 20 additions & 0 deletions Funcky/Extensions/ParseExtensions/ParseExtensions.GenericNumber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#if GENERIC_MATH
using System.Globalization;
using System.Numerics;

namespace Funcky.Extensions;
public static partial class ParseExtensions
{
public static Option<TNumber> ParseNumberOrNone<TNumber>(this string value, NumberStyles style, IFormatProvider? provider)
where TNumber : INumberBase<TNumber>
=> TNumber.TryParse(value, style, provider, out var result)
? result
: Option<TNumber>.None;

public static Option<TNumber> ParseNumberOrNone<TNumber>(this ReadOnlySpan<char> value, NumberStyles style, IFormatProvider? provider)
where TNumber : INumberBase<TNumber>
=> TNumber.TryParse(value, style, provider, out var result)
? result
: Option<TNumber>.None;
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#if GENERIC_PARSEABLE
namespace Funcky.Extensions;

public static partial class ParseExtensions
{
public static Option<TParseable> ParseOrNone<TParseable>(this ReadOnlySpan<char> value, IFormatProvider? provider)
where TParseable : ISpanParsable<TParseable>
=> TParseable.TryParse(value, provider, out var result)
? result
: Option<TParseable>.None;

public static Option<TParseable> ParseOrNone<TParseable>(this string? value, IFormatProvider? provider)
where TParseable : IParsable<TParseable>
=> TParseable.TryParse(value, provider, out var result)
? result
: Option<TParseable>.None;
}
#endif
4 changes: 4 additions & 0 deletions Funcky/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@ Funcky.Monads.Result<TValidResult>.InspectError(System.Action<System.Exception!>
Funcky.Monads.Result<TValidResult>.OrElse(Funcky.Monads.Result<TValidResult> fallback) -> Funcky.Monads.Result<TValidResult>
Funcky.Monads.Result<TValidResult>.OrElse(System.Func<System.Exception!, Funcky.Monads.Result<TValidResult>>! fallback) -> Funcky.Monads.Result<TValidResult>
static Funcky.Extensions.EnumeratorExtensions.MoveNextOrNone<T>(this System.Collections.Generic.IEnumerator<T>! enumerator) -> Funcky.Monads.Option<T>
static Funcky.Extensions.ParseExtensions.ParseNumberOrNone<TNumber>(this string! value, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option<TNumber>
static Funcky.Extensions.ParseExtensions.ParseNumberOrNone<TNumber>(this System.ReadOnlySpan<char> value, System.Globalization.NumberStyles style, System.IFormatProvider? provider) -> Funcky.Monads.Option<TNumber>
static Funcky.Extensions.ParseExtensions.ParseOrNone<TParseable>(this string? value, System.IFormatProvider? provider) -> Funcky.Monads.Option<TParseable>
static Funcky.Extensions.ParseExtensions.ParseOrNone<TParseable>(this System.ReadOnlySpan<char> value, System.IFormatProvider? provider) -> Funcky.Monads.Option<TParseable>
static Funcky.Extensions.StringExtensions.Chunk(this string! source, int size) -> System.Collections.Generic.IEnumerable<string!>!
static Funcky.Extensions.StringExtensions.SlidingWindow(this string! source, int width) -> System.Collections.Generic.IEnumerable<string!>!

0 comments on commit 3ebf182

Please sign in to comment.