added empty error
.NET Test / .NET tests (push) Successful in 2m5s

This commit is contained in:
2026-07-12 20:30:35 +04:00
parent 848374972c
commit 4a7cdd6bf1
4 changed files with 247 additions and 15 deletions
+51 -3
View File
@@ -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
{
+8
View File
@@ -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();