+51
-3
@@ -58,7 +58,7 @@ public abstract class Error : IEquatable<Error>, IComparable<Error>
|
||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Error Many(Error error1, Error error2) => (error1, error2) switch
|
||||
{
|
||||
(null, null) => new ManyErrors(ImmutableArray<Error>.Empty),
|
||||
(null, null) => EmptyError.Instance,
|
||||
(Error err, null) => err,
|
||||
(Error err, { IsEmpty: true }) => err,
|
||||
(null, Error err) => err,
|
||||
@@ -70,8 +70,10 @@ public abstract class Error : IEquatable<Error>, IComparable<Error>
|
||||
/// </summary>
|
||||
/// <remarks>Collects many errors into a single <see cref="Error"/> type, called <see cref="ManyErrors"/></remarks>
|
||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Error Many(params Error[] errors) => errors.Length switch
|
||||
public static Error Many(params Error[] errors) => errors?.Length switch
|
||||
{
|
||||
null => EmptyError.Instance,
|
||||
0 => EmptyError.Instance,
|
||||
1 => errors[0],
|
||||
_ => new ManyErrors(errors)
|
||||
};
|
||||
@@ -80,7 +82,11 @@ public abstract class Error : IEquatable<Error>, IComparable<Error>
|
||||
/// </summary>
|
||||
/// <remarks>Collects many errors into a single <see cref="Error"/> type, called <see cref="ManyErrors"/></remarks>
|
||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Error Many(IEnumerable<Error> errors) => new ManyErrors(errors);
|
||||
public static Error Many(IEnumerable<Error> errors)
|
||||
{
|
||||
var result = new ManyErrors(errors);
|
||||
return result.IsEmpty ? EmptyError.Instance : result;
|
||||
}
|
||||
|
||||
[Pure] public abstract string Type { get; }
|
||||
[Pure] public abstract string Message { get; }
|
||||
@@ -93,6 +99,12 @@ public abstract class Error : IEquatable<Error>, IComparable<Error>
|
||||
[Pure] public abstract bool IsExpected { get; }
|
||||
[Pure] public abstract bool IsExceptional { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A reusable singleton representing the absence of an error (null-object pattern).
|
||||
/// </summary>
|
||||
[Pure]
|
||||
public static Error Empty => EmptyError.Instance;
|
||||
|
||||
[Pure] public Error Append(Error? next)
|
||||
{
|
||||
if (next is null || next.IsEmpty)
|
||||
@@ -153,6 +165,42 @@ public abstract class Error : IEquatable<Error>, IComparable<Error>
|
||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)] internal virtual Error AccessUnsafe(int position) => this;
|
||||
}
|
||||
|
||||
public sealed class EmptyError : Error
|
||||
{
|
||||
public static readonly EmptyError Instance = new();
|
||||
|
||||
private EmptyError() { }
|
||||
|
||||
[Pure] public override string Type => "empty";
|
||||
[Pure] public override string Message => "";
|
||||
[Pure] public override int Count => 0;
|
||||
[Pure] public override bool IsEmpty => true;
|
||||
[Pure] public override bool IsExpected => true;
|
||||
[Pure] public override bool IsExceptional => false;
|
||||
|
||||
[Pure]
|
||||
public override IEnumerable<Error> ToEnumerable() { yield break; }
|
||||
|
||||
[Pure]
|
||||
public override Exception ToException() =>
|
||||
new ErrorException(Type, Message);
|
||||
|
||||
[Pure]
|
||||
public override int CompareTo(Error? other) =>
|
||||
other is EmptyError ? 0 : -1;
|
||||
|
||||
[Pure]
|
||||
public override bool Equals(Error? other) =>
|
||||
ReferenceEquals(this, other) || (other?.IsEmpty == true);
|
||||
|
||||
[Pure]
|
||||
public override int GetHashCode() => 0;
|
||||
|
||||
[Pure]
|
||||
public override bool IsSimilarTo(Error? other) =>
|
||||
other is EmptyError || (other?.IsEmpty == true);
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(ExpectedErrorJsonConverter))]
|
||||
public sealed class ExpectedError : Error
|
||||
{
|
||||
|
||||
@@ -18,11 +18,19 @@ public sealed class ErrorJsonConverter : JsonConverter<Error>
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Error value, JsonSerializerOptions options)
|
||||
{
|
||||
if (value is EmptyError)
|
||||
{
|
||||
writer.WriteNullValue();
|
||||
return;
|
||||
}
|
||||
|
||||
if (value is ManyErrors manyErrors)
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
foreach (var err in manyErrors)
|
||||
{
|
||||
if (err.IsEmpty)
|
||||
continue;
|
||||
WriteOne(writer, err);
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
|
||||
Reference in New Issue
Block a user