Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/RustyOptions.Tests/OptionParseTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
#if NET7_0_OR_GREATER

using static RustyOptions.Option;
using System.Globalization;

namespace RustyOptions.Tests
{
public class OptionParseTests
{
public OptionParseTests()
{
CultureInfo.CurrentCulture = new CultureInfo("en-US");
}

[Fact]
public void CanParseStrings()
{
Expand Down
14 changes: 14 additions & 0 deletions src/RustyOptions.Tests/ResultTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ public void CanPerformBasicOperationsStructClass()
var errStr2 = Err<int, string>("Whoops!");

Assert.True(okInt.IsOk(out var o1) && o1 == 42);
Assert.True(okInt.IsOkAnd(n => n == 42, out _));
Assert.True(errStr.IsErr(out var e1) && e1 == "Whoops!");
Assert.True(errStr.IsErrAnd(s => s == "Whoops!", out _));
Assert.False(okInt.IsErr(out _));
Assert.False(errStr.IsOk(out _));

Assert.False(okInt.IsOkAnd(null, out _));
Assert.False(errStr.IsOkAnd(null, out _));

Assert.True(okInt == okInt2);
Assert.Equal(okInt, okInt2);
Assert.True(okInt.Equals((object)okInt2));
Expand All @@ -38,7 +43,10 @@ public void CanPerformBasicOperationsClassStruct()
var errInt2 = Err<string, int>(-1);

Assert.True(okStr.IsOk(out var o1) && o1 == "Foo");
Assert.True(okStr.IsOkAnd(s => s == "Foo", out _));

Assert.True(errInt.IsErr(out var e1) && e1 == -1);
Assert.True(errInt.IsErrAnd(n => n == -1, out _));
Assert.False(okStr.IsErr(out _));
Assert.False(errInt.IsOk(out _));

Expand All @@ -58,7 +66,9 @@ public void CanCreateWithStringErr()
var err = Err<int>("oops");

Assert.True(ok.IsOk(out var okVal) && okVal == 42);
Assert.True(ok.IsOkAnd(n => n == 42, out _));
Assert.True(err.IsErr(out var errVal) && errVal == "oops");
Assert.True(err.IsErrAnd(err => err == "oops", out _));
}

[Fact]
Expand All @@ -68,7 +78,9 @@ public void CanCreateWithExceptionErr()
var err = Err<int>(new InvalidOperationException("oops"));

Assert.True(ok.IsOk(out var okVal) && okVal == 42);
Assert.True(ok.IsOkAnd(n => n == 42, out _));
Assert.True(err.IsErr(out var ex) && ex?.Message == "oops");
Assert.True(err.IsErrAnd(exc => exc.Message == "oops", out _));
}

[Fact]
Expand Down Expand Up @@ -187,7 +199,9 @@ public void CanTry()
int DoesNotThrow() => new[] { 42 }[0];

Assert.True(Result.Try(Throws).IsErr(out var ex) && ex is IndexOutOfRangeException);
Assert.True(Result.Try(Throws).IsErrAnd(exc => exc is IndexOutOfRangeException, out _));
Assert.True(Result.Try(DoesNotThrow).IsOk(out var val) && val == 42);
Assert.True(Result.Try(DoesNotThrow).IsOkAnd(n => n == 42, out _));
}

[Fact]
Expand Down
31 changes: 31 additions & 0 deletions src/RustyOptions/Result{T,TErr}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -544,4 +544,35 @@ public int CompareTo(Result<T, TErr> other)
/// <returns><c>true</c> if the <paramref name="left"/> parameter is less than or equal to the <paramref name="right"/> parameter.</returns>
public static bool operator <=(Result<T, TErr> left, Result<T, TErr> right)
=> left.CompareTo(right) <= 0;

/// <summary>
/// Checks whether the result is <c>Ok</c> and applies the given <paramref name="predicate"/>
/// to the value if it is. Returns <c>true</c> if both conditions are met; otherwise, returns <c>false</c>.
/// The resulting value is output through the <paramref name="value"/> parameter, which will be <c>null</c>
/// if the result is not <c>Ok</c>.
/// </summary>
/// <param name="predicate">The function to evaluate the value when the result is <c>Ok</c>.</param>
/// <param name="value">When this method returns, contains the value if the result is <c>Ok</c>; otherwise, <c>null</c>.</param>
/// <returns><c>true</c> if the result is <c>Ok</c> and the predicate returns <c>true</c>; otherwise, <c>false</c>.</returns>
public bool IsOkAnd(Func<T, bool> predicate, [MaybeNullWhen(false)] out T value)
{
value = _value;
return predicate != null && _isOk && predicate(_value);
}

/// <summary>
/// Checks whether the result is <c>Err</c> and applies the given <paramref name="predicate"/>
/// to the error value if it is. Returns <c>true</c> if both conditions are met; otherwise, returns <c>false</c>.
/// The resulting error value is output through the <paramref name="error"/> parameter, which will be <c>null</c>
/// if the result is not <c>Err</c>.
/// </summary>
/// <param name="predicate">The function to evaluate the error value when the result is <c>Err</c>.</param>
/// <param name="error">When this method returns, contains the error value if the result is <c>Err</c>; otherwise, <c>null</c>.</param>
/// <returns><c>true</c> if the result is <c>Err</c> and the predicate returns <c>true</c>; otherwise, <c>false</c>.</returns>
public bool IsErrAnd(Func<TErr, bool> predicate, [MaybeNullWhen(false)] out TErr error)
{
error = _err;
return predicate != null && !_isOk && predicate(_err);
}

}