-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#48 - Added ValueOrError<TValue,TError>
STill a couple of tests missing, but the basic functionality is there.
- Loading branch information
Showing
19 changed files
with
700 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | ||
<s:Boolean x:Key="/Default/UserDictionary/Words/=analyser/@EntryIndexedValue">True</s:Boolean> | ||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Succinc/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System; | ||
using SuccincT.Unions.PatternMatchers; | ||
|
||
namespace SuccincT.Options | ||
{ | ||
public interface IValueOrErrorActionMatcher<TValue, TError> | ||
{ | ||
IUnionActionPatternCaseHandler<IValueOrErrorActionMatcher<TValue, TError>, TValue> Value(); | ||
|
||
IUnionActionPatternCaseHandler<IValueOrErrorActionMatcher<TValue, TError>, TError> Error(); | ||
|
||
IUnionActionPatternMatcherAfterElse Else(Action<ValueOrError<TValue, TError>> elseAction); | ||
|
||
IUnionActionPatternMatcherAfterElse IgnoreElse(); | ||
|
||
void Exec(); | ||
} | ||
} |
File renamed without changes.
18 changes: 18 additions & 0 deletions
18
src/SuccincT/Options/IValueOrErrorFuncMatcher{TV,TE,TR}.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System; | ||
using SuccincT.Unions.PatternMatchers; | ||
|
||
namespace SuccincT.Options | ||
{ | ||
public interface IValueOrErrorFuncMatcher<TValue, TError, TResult> | ||
{ | ||
IUnionFuncPatternCaseHandler<IValueOrErrorFuncMatcher<TValue, TError, TResult>, TValue, TResult> Value(); | ||
|
||
IUnionFuncPatternCaseHandler<IValueOrErrorFuncMatcher<TValue, TError, TResult>, TError, TResult> Error(); | ||
|
||
IUnionFuncPatternMatcherAfterElse<TResult> Else(Func<ValueOrError<TValue, TError>, TResult> elseAction); | ||
|
||
IUnionFuncPatternMatcherAfterElse<TResult> Else(TResult value); | ||
|
||
TResult Result(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
using SuccincT.Functional; | ||
using SuccincT.PatternMatchers; | ||
using SuccincT.Unions.PatternMatchers; | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace SuccincT.Options | ||
{ | ||
internal sealed class ValueOrErrorMatcher<TValue, TError, TResult> : IUnionFuncPatternMatcherAfterElse<TResult>, | ||
IValueOrErrorFuncMatcher<TValue, | ||
TError, | ||
TResult>, | ||
IValueOrErrorActionMatcher<TValue, TError>, | ||
IUnionActionPatternMatcherAfterElse | ||
{ | ||
private readonly ValueOrError<TValue, TError> _valueOrError; | ||
|
||
private readonly MatchFunctionSelector<TValue, TValue, TResult> _valueFunctionSelector = | ||
new MatchFunctionSelector<TValue, TValue, TResult>( | ||
x => throw new NoMatchException("No match action defined for ValueOrError with value")); | ||
|
||
private readonly MatchFunctionSelector<TError, TError, TResult> _errorFunctionSelector = | ||
new MatchFunctionSelector<TError, TError, TResult>( | ||
x => throw new NoMatchException("No match action defined for ValueOrError with value")); | ||
|
||
private Func<ValueOrError<TValue, TError>, TResult> _elseAction; | ||
|
||
internal ValueOrErrorMatcher(ValueOrError<TValue, TError> valueOrError) => _valueOrError = valueOrError; | ||
|
||
IUnionFuncPatternCaseHandler<IValueOrErrorFuncMatcher<TValue, TError, TResult>, TValue, TResult> | ||
IValueOrErrorFuncMatcher<TValue, TError, TResult>.Value() | ||
{ | ||
return new UnionPatternCaseHandler<IValueOrErrorFuncMatcher<TValue, TError, TResult>, TValue, TResult>( | ||
RecordValueAction, | ||
this); | ||
} | ||
|
||
IUnionFuncPatternCaseHandler<IValueOrErrorFuncMatcher<TValue, TError, TResult>, TError, TResult> | ||
IValueOrErrorFuncMatcher<TValue, TError, TResult>.Error() | ||
{ | ||
return new UnionPatternCaseHandler<IValueOrErrorFuncMatcher<TValue, TError, TResult>, TError, TResult>( | ||
RecordErrorAction, | ||
this); | ||
} | ||
|
||
IUnionFuncPatternMatcherAfterElse<TResult> IValueOrErrorFuncMatcher<TValue, TError, TResult>.Else(TResult value) | ||
{ | ||
_elseAction = _ => value; | ||
return this; | ||
} | ||
|
||
IUnionFuncPatternMatcherAfterElse<TResult> IValueOrErrorFuncMatcher<TValue, TError, TResult>.Else( | ||
Func<ValueOrError<TValue, TError>, TResult> elseAction) | ||
{ | ||
_elseAction = elseAction; | ||
return this; | ||
} | ||
|
||
TResult IValueOrErrorFuncMatcher<TValue, TError, TResult>.Result() | ||
{ | ||
return _valueOrError.HasValue | ||
? _valueFunctionSelector.DetermineResultUsingDefaultIfRequired(_valueOrError.Value) | ||
: _errorFunctionSelector.DetermineResultUsingDefaultIfRequired(_valueOrError.Error); | ||
} | ||
|
||
IUnionActionPatternCaseHandler<IValueOrErrorActionMatcher<TValue, TError>, TValue> | ||
IValueOrErrorActionMatcher<TValue, TError>.Value() | ||
{ | ||
return new UnionPatternCaseHandler<IValueOrErrorActionMatcher<TValue, TError>, TValue, TResult>( | ||
RecordValueAction, | ||
this); | ||
} | ||
|
||
|
||
IUnionActionPatternCaseHandler<IValueOrErrorActionMatcher<TValue, TError>, TError> | ||
IValueOrErrorActionMatcher<TValue, TError>.Error() | ||
{ | ||
return new UnionPatternCaseHandler<IValueOrErrorActionMatcher<TValue, TError>, TError, TResult>( | ||
RecordErrorAction, | ||
this); | ||
} | ||
|
||
IUnionActionPatternMatcherAfterElse IValueOrErrorActionMatcher<TValue, TError>.Else( | ||
Action<ValueOrError<TValue, TError>> elseAction) | ||
{ | ||
_elseAction = elseAction.ToUnitFunc() as Func<ValueOrError<TValue, TError>, TResult>; | ||
return this; | ||
} | ||
|
||
IUnionActionPatternMatcherAfterElse IValueOrErrorActionMatcher<TValue, TError>.IgnoreElse() | ||
{ | ||
_elseAction = x => default; | ||
return this; | ||
} | ||
|
||
void IValueOrErrorActionMatcher<TValue, TError>.Exec() | ||
{ | ||
_ = _valueOrError.HasValue | ||
? _valueFunctionSelector.DetermineResultUsingDefaultIfRequired(_valueOrError.Value) | ||
: _errorFunctionSelector.DetermineResultUsingDefaultIfRequired(_valueOrError.Error); | ||
} | ||
|
||
TResult IUnionFuncPatternMatcherAfterElse<TResult>.Result() | ||
{ | ||
var possibleResult = _valueOrError.HasValue | ||
? _valueFunctionSelector.DetermineResult(_valueOrError.Value) | ||
: _errorFunctionSelector.DetermineResult(_valueOrError.Error); | ||
|
||
return possibleResult.HasValue ? possibleResult.Value : _elseAction(_valueOrError); | ||
} | ||
|
||
void IUnionActionPatternMatcherAfterElse.Exec() | ||
{ | ||
var possibleResult = _valueOrError.HasValue | ||
? _valueFunctionSelector.DetermineResult(_valueOrError.Value) | ||
: _errorFunctionSelector.DetermineResult(_valueOrError.Error); | ||
|
||
_ = possibleResult.HasValue ? possibleResult.Value : _elseAction(_valueOrError); | ||
} | ||
|
||
private void RecordValueAction(Func<TValue, IList<TValue>, bool> withTest, | ||
Func<TValue, bool> whereTest, | ||
IList<TValue> withValues, | ||
Func<TValue, TResult> action) | ||
=> _valueFunctionSelector.AddTestAndAction(withTest, withValues, whereTest, action); | ||
|
||
private void RecordErrorAction(Func<TError, IList<TError>, bool> withTest, | ||
Func<TError, bool> whereTest, | ||
IList<TError> withValues, | ||
Func<TError, TResult> action) | ||
=> _errorFunctionSelector.AddTestAndAction(withTest, withValues, whereTest, action); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
using System; | ||
using SuccincT.Functional; | ||
|
||
namespace SuccincT.Options | ||
{ | ||
public readonly struct ValueOrError<TValue, TError> | ||
{ | ||
private readonly TValue _value; | ||
private readonly TError _error; | ||
|
||
private ValueOrError(TValue value, TError error, bool hasValue) | ||
=> (_value, _error, HasValue) = (value, error, hasValue); | ||
|
||
/// <summary> | ||
/// Creates a new instance with a value (and no error) | ||
/// </summary> | ||
public static ValueOrError<TValue, TError> WithValue(TValue value) | ||
=> new ValueOrError<TValue, TError>(value, default, true); | ||
|
||
/// <summary> | ||
/// Creates a new instance with an error (and no value) | ||
/// </summary> | ||
public static ValueOrError<TValue, TError> WithError(TError error) | ||
=> new ValueOrError<TValue, TError>(default, error, false); | ||
|
||
/// <summary> | ||
/// Provides a fluent matcher that ultimately (upon Result() being called) returns a TResult value | ||
/// by invoking the function associated with the match. | ||
/// </summary> | ||
public IValueOrErrorFuncMatcher<TValue, TError, TResult> Match<TResult>() | ||
=> new ValueOrErrorMatcher<TValue, TError, TResult>(this); | ||
|
||
/// <summary> | ||
/// Provides a fluent matcher that ultimately (upon Exec() being called) invokes the Action | ||
/// associated with the match. | ||
/// </summary> | ||
public IValueOrErrorActionMatcher<TValue, TError> Match() | ||
=> new ValueOrErrorMatcher<TValue, TError, Unit>(this); | ||
|
||
/// <summary> | ||
/// True if created via WithValue(), else false. | ||
/// </summary> | ||
public bool HasValue { get; } | ||
|
||
/// <summary> | ||
/// The value held (if created by WithValue()). Will throw an InvalidOperationException if created via | ||
/// WithError(). | ||
/// </summary> | ||
public TValue Value | ||
=> HasValue ? _value : throw new InvalidOperationException("ValueOrError doesn't contain a value"); | ||
|
||
/// <summary> | ||
/// The error held (if created by WithError()). Will throw an InvalidOperationException if created via | ||
/// WithValue(). | ||
/// </summary> | ||
public TError Error | ||
=> !HasValue ? _error : throw new InvalidOperationException("ValueOrError doesn't contain an error"); | ||
|
||
public override string ToString() => HasValue ? $"Value of {_value}" : $"Error of {_error}"; | ||
|
||
public override bool Equals(object obj) | ||
{ | ||
switch (obj) | ||
{ | ||
case ValueOrError<TValue, TError> other: return other.HasValue == HasValue && ValueOrErrorsEqual(other); | ||
case null: return HasValue && _value == null || !HasValue && _error == null; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
private bool ValueOrErrorsEqual(in ValueOrError<TValue, TError> other) | ||
{ | ||
return HasValue | ||
? _value == null && other.HasValue && other.Value == null || | ||
_value != null && _value.Equals(other.Value) | ||
: _error == null && !other.HasValue && other.Error == null || | ||
_error != null && _error.Equals(other.Error); | ||
} | ||
|
||
public override int GetHashCode() => HasValue ? _value.GetHashCode() : _error.GetHashCode(); | ||
|
||
public static bool operator ==(ValueOrError<TValue, TError> a, ValueOrError<TValue, TError> b) => a.Equals(b); | ||
|
||
public static bool operator !=(ValueOrError<TValue, TError> a, ValueOrError<TValue, TError> b) => !a.Equals(b); | ||
} | ||
} |
Oops, something went wrong.