using System; namespace Wabbajack { public struct GetResponse : IEquatable>, IErrorResponse { public static readonly GetResponse Failure = new GetResponse(); public readonly T Value; public readonly bool Succeeded; public readonly Exception? Exception; private readonly string _reason; public bool Failed => !Succeeded; public string Reason { get { if (Exception != null) { return Exception.ToString(); } return _reason; } } bool IErrorResponse.Succeeded => Succeeded; Exception? IErrorResponse.Exception => Exception; private GetResponse( bool succeeded, T? val = default, string? reason = null, Exception? ex = null) { Value = val!; Succeeded = succeeded; _reason = reason ?? string.Empty; Exception = ex; } public bool Equals(GetResponse other) { return Succeeded == other.Succeeded && Equals(Value, other.Value); } public override bool Equals(object? obj) { if (!(obj is GetResponse rhs)) return false; return Equals(rhs); } public override int GetHashCode() { System.HashCode hash = new HashCode(); hash.Add(Value); hash.Add(Succeeded); return hash.ToHashCode(); } public override string ToString() { return $"({(Succeeded ? "Success" : "Fail")}, {Value}, {Reason})"; } public GetResponse BubbleFailure() { return new GetResponse( succeeded: false, reason: _reason, ex: Exception); } public GetResponse Bubble(Func conv) { return new GetResponse( succeeded: Succeeded, val: conv(Value), reason: _reason, ex: Exception); } public T EvaluateOrThrow() { if (Succeeded) { return Value; } throw new ArgumentException(Reason); } #region Factories public static GetResponse Succeed(T value) { return new GetResponse(true, value); } public static GetResponse Succeed(T value, string reason) { return new GetResponse(true, value, reason); } public static GetResponse Fail(string reason) { return new GetResponse(false, reason: reason); } public static GetResponse Fail(T val, string reason) { return new GetResponse(false, val, reason); } public static GetResponse Fail(Exception ex) { return new GetResponse(false, ex: ex); } public static GetResponse Fail(T val, Exception ex) { return new GetResponse(false, val, ex: ex); } public static GetResponse Fail(T val) { return new GetResponse(false, val); } public static GetResponse Create(bool successful, T? val = default(T), string? reason = null) { return new GetResponse(successful, val!, reason); } #endregion } }