Compare commits
10 Commits
546d24c2ec
...
77396d252e
| Author | SHA1 | Date | |
|---|---|---|---|
| 77396d252e | |||
| d2fe7edbce | |||
| e60be738a9 | |||
| 314b706d61 | |||
| e4129b1c09 | |||
| 82428641b6 | |||
| ce71765cb4 | |||
| ee5eeedb50 | |||
| 27e891e80e | |||
| 766eb8a8c2 |
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -18,15 +19,23 @@ public class Error(string message, string? details = null, string? devDetails =
|
|||||||
public readonly string? Details = details;
|
public readonly string? Details = details;
|
||||||
public readonly string? DevDetails = devDetails;
|
public readonly string? DevDetails = devDetails;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
private readonly StackTrace _stackTrace = new();
|
||||||
|
#endif
|
||||||
|
|
||||||
public virtual Exception GetException()
|
public virtual Exception GetException()
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
return new Exception(ToString());
|
||||||
|
#else
|
||||||
return new Exception(Message);
|
return new Exception(Message);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
return $"{Message}\n{Details}\n{DevDetails}";
|
return $"{Message}\n{Details}\n{DevDetails}\nTrace:{_stackTrace}";
|
||||||
#else
|
#else
|
||||||
return $"{Message}\n{Details}";
|
return $"{Message}\n{Details}";
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -33,4 +33,9 @@ public class ExceptionError<T> : Error where T : Exception
|
|||||||
{
|
{
|
||||||
return $"{Message}\n{Exception}";
|
return $"{Message}\n{Exception}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static implicit operator ExceptionError<T>(T exception)
|
||||||
|
{
|
||||||
|
return new ExceptionError<T>(exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -46,13 +46,79 @@ public interface IMaybe<T, E> where E : Error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly struct MaybeEx<T, Ex> : IMaybe<T, ExceptionError<Ex>> where Ex : Exception
|
||||||
|
{
|
||||||
|
[MemberNotNullWhen(true, nameof(Error))]
|
||||||
|
[MemberNotNullWhen(false, nameof(_value))]
|
||||||
|
public readonly bool HasError { get; }
|
||||||
|
public readonly bool HasValue => !HasError;
|
||||||
|
public readonly ExceptionError<Ex>? Error { get; init; }
|
||||||
|
public readonly T Value => HasError ? throw Error.GetException() : _value;
|
||||||
|
private readonly T? _value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="Maybe{T, Ex}"/> with a default(null) value
|
||||||
|
/// </summary>
|
||||||
|
public MaybeEx()
|
||||||
|
{
|
||||||
|
_value = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="Maybe{T, Ex}"/> with a <paramref name="value"/>
|
||||||
|
/// </summary>
|
||||||
|
public MaybeEx(T value)
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="Maybe{T, Ex}"/> with an exception error <paramref name="e"/>
|
||||||
|
/// </summary>
|
||||||
|
public MaybeEx(Ex e)
|
||||||
|
{
|
||||||
|
Error = e;
|
||||||
|
HasError = true;
|
||||||
|
_value = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static implicit operator MaybeEx<T, Ex>(T value)
|
||||||
|
{
|
||||||
|
return new MaybeEx<T, Ex>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator MaybeEx<T, Ex>(Ex e)
|
||||||
|
{
|
||||||
|
return new MaybeEx<T, Ex>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Maybe<T, ExceptionError<Ex>>(MaybeEx<T, Ex> value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Maybe<T>(MaybeEx<T, Ex> value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator T(MaybeEx<T, Ex> value)
|
||||||
|
{
|
||||||
|
if (value.HasError)
|
||||||
|
throw value.Error.GetException();
|
||||||
|
return value.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public readonly struct Maybe<T, E> : IMaybe<T, E> where E: Error
|
public readonly struct Maybe<T, E> : IMaybe<T, E> where E: Error
|
||||||
{
|
{
|
||||||
[MemberNotNullWhen(true, nameof(Error))]
|
[MemberNotNullWhen(true, nameof(Error))]
|
||||||
|
[MemberNotNullWhen(false, nameof(_value))]
|
||||||
public readonly bool HasError { get; }
|
public readonly bool HasError { get; }
|
||||||
public readonly bool HasValue => !HasError;
|
public readonly bool HasValue => !HasError;
|
||||||
public readonly E? Error { get; }
|
public readonly E? Error { get; init; }
|
||||||
public readonly T Value => HasError ? throw Error.GetException() : _value!;
|
public readonly T Value => HasError ? throw Error.GetException() : _value;
|
||||||
|
|
||||||
private readonly T? _value;
|
private readonly T? _value;
|
||||||
|
|
||||||
@@ -82,6 +148,7 @@ public readonly struct Maybe<T, E> : IMaybe<T, E> where E: Error
|
|||||||
_value = default;
|
_value = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static implicit operator Maybe<T, E>(T value)
|
public static implicit operator Maybe<T, E>(T value)
|
||||||
{
|
{
|
||||||
return new Maybe<T, E>(value);
|
return new Maybe<T, E>(value);
|
||||||
@@ -92,6 +159,11 @@ public readonly struct Maybe<T, E> : IMaybe<T, E> where E: Error
|
|||||||
return new Maybe<T, E>(e);
|
return new Maybe<T, E>(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static implicit operator Maybe<T>(Maybe<T, E> value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
public static implicit operator T(Maybe<T, E> value)
|
public static implicit operator T(Maybe<T, E> value)
|
||||||
{
|
{
|
||||||
if (value.HasError)
|
if (value.HasError)
|
||||||
@@ -104,10 +176,11 @@ public readonly struct Maybe<T, E> : IMaybe<T, E> where E: Error
|
|||||||
public readonly struct Maybe<T> : IMaybe<T, Error>
|
public readonly struct Maybe<T> : IMaybe<T, Error>
|
||||||
{
|
{
|
||||||
[MemberNotNullWhen(true, nameof(Error))]
|
[MemberNotNullWhen(true, nameof(Error))]
|
||||||
|
[MemberNotNullWhen(false, nameof(_value))]
|
||||||
public readonly bool HasError { get; }
|
public readonly bool HasError { get; }
|
||||||
public readonly bool HasValue => !HasError;
|
public readonly bool HasValue => !HasError;
|
||||||
public readonly Error? Error { get; }
|
public readonly Error? Error { get; }
|
||||||
public readonly T Value => HasError ? throw Error.GetException() : _value!;
|
public readonly T Value => HasError ? throw Error.GetException() : _value;
|
||||||
|
|
||||||
private readonly T? _value;
|
private readonly T? _value;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageId>MaybeError</PackageId>
|
<PackageId>MaybeError</PackageId>
|
||||||
<Version>1.0.2</Version>
|
<Version>1.2.0</Version>
|
||||||
<Authors>Amatsugu</Authors>
|
<Authors>Amatsugu</Authors>
|
||||||
<PackageDescription>Errors as values</PackageDescription>
|
<PackageDescription>Errors as values</PackageDescription>
|
||||||
<RepositoryUrl>https://github.com/Amatsugu/MaybeError</RepositoryUrl>
|
<RepositoryUrl>https://github.com/Amatsugu/MaybeError</RepositoryUrl>
|
||||||
|
|||||||
@@ -37,6 +37,20 @@ public static class MaybeExtensions
|
|||||||
return predicate(maybe.Value);
|
return predicate(maybe.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ValueMaybe<T2, E> Map<T, T2, E>(this IValueMaybe<T, E> maybe, Func<T, T2> map) where T : struct where T2 : struct where E : Error
|
||||||
|
{
|
||||||
|
if (maybe.HasError)
|
||||||
|
return maybe.Error;
|
||||||
|
return map(maybe.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ValueMaybe<T, E2> MapError<T, E, E2>(this IValueMaybe<T, E> maybe, Func<E, E2> map) where T : struct where E : Error where E2 : Error
|
||||||
|
{
|
||||||
|
if (!maybe.HasError)
|
||||||
|
return maybe.Value;
|
||||||
|
return map(maybe.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static T ValueOrDefault<T, E>(this IMaybe<T, E> maybe, T defaultValue) where E : Error
|
public static T ValueOrDefault<T, E>(this IMaybe<T, E> maybe, T defaultValue) where E : Error
|
||||||
{
|
{
|
||||||
@@ -70,4 +84,19 @@ public static class MaybeExtensions
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
return predicate(maybe.Value);
|
return predicate(maybe.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Maybe<T2, E> Map<T, T2, E>(this IMaybe<T, E> maybe, Func<T, T2> map) where E : Error
|
||||||
|
{
|
||||||
|
if (maybe.HasError)
|
||||||
|
return maybe.Error;
|
||||||
|
return map(maybe.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Maybe<T, E2> MapError<T, E, E2>(this IMaybe<T, E> maybe, Func<E, E2> map) where E : Error where E2 : Error
|
||||||
|
{
|
||||||
|
if (!maybe.HasError)
|
||||||
|
return maybe.Value;
|
||||||
|
return map(maybe.Error);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ public interface IValueMaybe<T, E> where T : struct where E : Error
|
|||||||
{
|
{
|
||||||
[MemberNotNullWhen(true, nameof(Error))]
|
[MemberNotNullWhen(true, nameof(Error))]
|
||||||
bool HasError { get; }
|
bool HasError { get; }
|
||||||
|
[MemberNotNullWhen(false, nameof(Error))]
|
||||||
bool HasValue => !HasError;
|
bool HasValue => !HasError;
|
||||||
E? Error { get; }
|
E? Error { get; }
|
||||||
T Value { get; }
|
T Value { get; }
|
||||||
@@ -18,6 +19,7 @@ public readonly struct ValueMaybe<T, E> : IValueMaybe<T, E> where T : struct whe
|
|||||||
{
|
{
|
||||||
[MemberNotNullWhen(true, nameof(Error))]
|
[MemberNotNullWhen(true, nameof(Error))]
|
||||||
public readonly bool HasError { get; }
|
public readonly bool HasError { get; }
|
||||||
|
[MemberNotNullWhen(false, nameof(Error))]
|
||||||
public readonly bool HasValue => !HasError;
|
public readonly bool HasValue => !HasError;
|
||||||
public readonly E? Error { get; }
|
public readonly E? Error { get; }
|
||||||
public readonly T Value => HasError ? throw Error.GetException() : _value;
|
public readonly T Value => HasError ? throw Error.GetException() : _value;
|
||||||
@@ -61,6 +63,11 @@ public readonly struct ValueMaybe<T, E> : IValueMaybe<T, E> where T : struct whe
|
|||||||
return new ValueMaybe<T, E>(e);
|
return new ValueMaybe<T, E>(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static implicit operator ValueMaybe<T>(ValueMaybe<T, E> value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
public static implicit operator T(ValueMaybe<T, E> value)
|
public static implicit operator T(ValueMaybe<T, E> value)
|
||||||
{
|
{
|
||||||
if (value.HasError)
|
if (value.HasError)
|
||||||
@@ -138,3 +145,68 @@ public readonly struct ValueMaybe<T> : IValueMaybe<T, Error> where T : struct
|
|||||||
return value.Value;
|
return value.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public readonly struct ValueMaybeEx<T, Ex> : IMaybe<T, ExceptionError<Ex>> where T: struct where Ex : Exception
|
||||||
|
{
|
||||||
|
[MemberNotNullWhen(true, nameof(Error))]
|
||||||
|
public readonly bool HasError { get; }
|
||||||
|
public readonly bool HasValue => !HasError;
|
||||||
|
public readonly ExceptionError<Ex>? Error { get; init; }
|
||||||
|
public readonly T Value => HasError ? throw Error.GetException() : _value!;
|
||||||
|
private readonly T _value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="Maybe{T, Ex}"/> with a default(null) value
|
||||||
|
/// </summary>
|
||||||
|
public ValueMaybeEx()
|
||||||
|
{
|
||||||
|
_value = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="Maybe{T, Ex}"/> with a <paramref name="value"/>
|
||||||
|
/// </summary>
|
||||||
|
public ValueMaybeEx(T value)
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="Maybe{T, Ex}"/> with an exception error <paramref name="e"/>
|
||||||
|
/// </summary>
|
||||||
|
public ValueMaybeEx(Ex e)
|
||||||
|
{
|
||||||
|
Error = e;
|
||||||
|
HasError = true;
|
||||||
|
_value = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static implicit operator ValueMaybeEx<T, Ex>(T value)
|
||||||
|
{
|
||||||
|
return new ValueMaybeEx<T, Ex>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ValueMaybeEx<T, Ex>(Ex e)
|
||||||
|
{
|
||||||
|
return new ValueMaybeEx<T, Ex>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ValueMaybe<T, ExceptionError<Ex>>(ValueMaybeEx<T, Ex> value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ValueMaybe<T>(ValueMaybeEx<T, Ex> value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator T(ValueMaybeEx<T, Ex> value)
|
||||||
|
{
|
||||||
|
if (value.HasError)
|
||||||
|
throw value.Error.GetException();
|
||||||
|
return value.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -115,4 +115,40 @@ public class MaybeTests
|
|||||||
value = new InvalidOperationException();
|
value = new InvalidOperationException();
|
||||||
Assert.That(value.AsOrDefault(v => v.Length, -4), Is.EqualTo(-4));
|
Assert.That(value.AsOrDefault(v => v.Length, -4), Is.EqualTo(-4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MapTest()
|
||||||
|
{
|
||||||
|
Maybe<string> value = "Test";
|
||||||
|
var valueMapped = value.Map(v => $"A{v}");
|
||||||
|
Assert.That(valueMapped.HasValue, Is.True);
|
||||||
|
Assert.That(valueMapped.Value, Is.EqualTo("ATest"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MapTestError()
|
||||||
|
{
|
||||||
|
Maybe<string> value = new Error("Err");
|
||||||
|
var valueMapped = value.Map(v => $"A{v}");
|
||||||
|
Assert.That(valueMapped.HasError, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MapErrorTest()
|
||||||
|
{
|
||||||
|
Maybe<string> value = "Test";
|
||||||
|
var valueMapped = value.MapError(v => new Error($"A{v}"));
|
||||||
|
Assert.That(valueMapped.HasValue, Is.True);
|
||||||
|
Assert.That(valueMapped.Value, Is.EqualTo("Test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MapErrorTestError()
|
||||||
|
{
|
||||||
|
Maybe<string> value = new Error("Err");
|
||||||
|
var valueMapped = value.MapError(v => new Error($"A{v.Message}"));
|
||||||
|
Assert.That(valueMapped.HasError, Is.True);
|
||||||
|
Assert.That(valueMapped.Error!.Message, Is.EqualTo("AErr"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -115,4 +115,40 @@ public class ValueMaybeTests
|
|||||||
value = new InvalidOperationException();
|
value = new InvalidOperationException();
|
||||||
Assert.That(value.AsOrDefault(v => v.ToString(), "err"), Is.EqualTo("err"));
|
Assert.That(value.AsOrDefault(v => v.ToString(), "err"), Is.EqualTo("err"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MapTest()
|
||||||
|
{
|
||||||
|
ValueMaybe<int> value = 1;
|
||||||
|
var valueMapped = value.Map(v => v + 1);
|
||||||
|
Assert.That(valueMapped.HasValue, Is.True);
|
||||||
|
Assert.That(valueMapped.Value, Is.EqualTo(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MapTestError()
|
||||||
|
{
|
||||||
|
ValueMaybe<int> value = new Error("Err");
|
||||||
|
var valueMapped = value.Map(v => v + 1);
|
||||||
|
Assert.That(valueMapped.HasError, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MapErrorTest()
|
||||||
|
{
|
||||||
|
Maybe<int> value = 1;
|
||||||
|
var valueMapped = value.MapError(v => new Error($"A{v}"));
|
||||||
|
Assert.That(valueMapped.HasValue, Is.True);
|
||||||
|
Assert.That(valueMapped.Value, Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MapErrorTestError()
|
||||||
|
{
|
||||||
|
ValueMaybe<int> value = new Error("Err");
|
||||||
|
var valueMapped = value.MapError(v => new Error($"A{v.Message}"));
|
||||||
|
Assert.That(valueMapped.HasError, Is.True);
|
||||||
|
Assert.That(valueMapped.Error!.Message, Is.EqualTo("AErr"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user