mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Ported some Error/Hash systems from Noggog/CSharpExt
This commit is contained in:
parent
bb4141dd79
commit
2dc47d5ec8
88
Wabbajack.Common/Error States/ErrorResponse.cs
Normal file
88
Wabbajack.Common/Error States/ErrorResponse.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Wabbajack
|
||||||
|
{
|
||||||
|
public struct ErrorResponse : IErrorResponse
|
||||||
|
{
|
||||||
|
public readonly static ErrorResponse Success = Succeed();
|
||||||
|
public readonly static ErrorResponse Failure = new ErrorResponse();
|
||||||
|
|
||||||
|
public readonly bool Succeeded;
|
||||||
|
public readonly Exception Exception;
|
||||||
|
private readonly string _reason;
|
||||||
|
|
||||||
|
public bool Failed => !Succeeded;
|
||||||
|
public string Reason
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (this.Exception != null)
|
||||||
|
{
|
||||||
|
return this.Exception.ToString();
|
||||||
|
}
|
||||||
|
return _reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IErrorResponse.Succeeded => this.Succeeded;
|
||||||
|
Exception IErrorResponse.Exception => this.Exception;
|
||||||
|
|
||||||
|
private ErrorResponse(
|
||||||
|
bool succeeded,
|
||||||
|
string reason = null,
|
||||||
|
Exception ex = null)
|
||||||
|
{
|
||||||
|
this.Succeeded = succeeded;
|
||||||
|
this._reason = reason;
|
||||||
|
this.Exception = ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"({(Succeeded ? "Success" : "Fail")}, {Reason})";
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Factories
|
||||||
|
public static ErrorResponse Succeed()
|
||||||
|
{
|
||||||
|
return new ErrorResponse(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ErrorResponse Succeed(string reason)
|
||||||
|
{
|
||||||
|
return new ErrorResponse(true, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ErrorResponse Fail(string reason)
|
||||||
|
{
|
||||||
|
return new ErrorResponse(false, reason: reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ErrorResponse Fail(Exception ex)
|
||||||
|
{
|
||||||
|
return new ErrorResponse(false, ex: ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ErrorResponse Fail()
|
||||||
|
{
|
||||||
|
return new ErrorResponse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ErrorResponse Create(bool successful, string reason = null)
|
||||||
|
{
|
||||||
|
return new ErrorResponse(successful, reason);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IErrorResponse
|
||||||
|
{
|
||||||
|
bool Succeeded { get; }
|
||||||
|
Exception Exception { get; }
|
||||||
|
string Reason { get; }
|
||||||
|
}
|
||||||
|
}
|
137
Wabbajack.Common/Error States/GetResponse.cs
Normal file
137
Wabbajack.Common/Error States/GetResponse.cs
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Wabbajack
|
||||||
|
{
|
||||||
|
public struct GetResponse<T> : IEquatable<GetResponse<T>>, IErrorResponse
|
||||||
|
{
|
||||||
|
public static readonly GetResponse<T> Failure = new GetResponse<T>();
|
||||||
|
|
||||||
|
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 (this.Exception != null)
|
||||||
|
{
|
||||||
|
return this.Exception.ToString();
|
||||||
|
}
|
||||||
|
return _reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IErrorResponse.Succeeded => this.Succeeded;
|
||||||
|
Exception IErrorResponse.Exception => this.Exception;
|
||||||
|
|
||||||
|
private GetResponse(
|
||||||
|
bool succeeded,
|
||||||
|
T val = default(T),
|
||||||
|
string reason = null,
|
||||||
|
Exception ex = null)
|
||||||
|
{
|
||||||
|
this.Value = val;
|
||||||
|
this.Succeeded = succeeded;
|
||||||
|
this._reason = reason;
|
||||||
|
this.Exception = ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(GetResponse<T> other)
|
||||||
|
{
|
||||||
|
return this.Succeeded == other.Succeeded
|
||||||
|
&& object.Equals(this.Value, other.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is GetResponse<T> rhs)) return false;
|
||||||
|
return Equals(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashHelper.GetHashCode(Value)
|
||||||
|
.CombineHashCode(Succeeded.GetHashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"({(Succeeded ? "Success" : "Fail")}, {Value}, {Reason})";
|
||||||
|
}
|
||||||
|
|
||||||
|
public GetResponse<R> BubbleFailure<R>()
|
||||||
|
{
|
||||||
|
return new GetResponse<R>(
|
||||||
|
succeeded: false,
|
||||||
|
reason: this._reason,
|
||||||
|
ex: this.Exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GetResponse<R> Bubble<R>(Func<T, R> conv)
|
||||||
|
{
|
||||||
|
return new GetResponse<R>(
|
||||||
|
succeeded: this.Succeeded,
|
||||||
|
val: conv(this.Value),
|
||||||
|
reason: this._reason,
|
||||||
|
ex: this.Exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T EvaluateOrThrow()
|
||||||
|
{
|
||||||
|
if (this.Succeeded)
|
||||||
|
{
|
||||||
|
return this.Value;
|
||||||
|
}
|
||||||
|
throw new ArgumentException(this.Reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Factories
|
||||||
|
public static GetResponse<T> Succeed(T value)
|
||||||
|
{
|
||||||
|
return new GetResponse<T>(true, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GetResponse<T> Succeed(T value, string reason)
|
||||||
|
{
|
||||||
|
return new GetResponse<T>(true, value, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GetResponse<T> Fail(string reason)
|
||||||
|
{
|
||||||
|
return new GetResponse<T>(false, reason: reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GetResponse<T> Fail(T val, string reason)
|
||||||
|
{
|
||||||
|
return new GetResponse<T>(false, val, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GetResponse<T> Fail(Exception ex)
|
||||||
|
{
|
||||||
|
return new GetResponse<T>(false, ex: ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GetResponse<T> Fail(T val, Exception ex)
|
||||||
|
{
|
||||||
|
return new GetResponse<T>(false, val, ex: ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GetResponse<T> Fail(T val)
|
||||||
|
{
|
||||||
|
return new GetResponse<T>(false, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GetResponse<T> Create(bool successful, T val = default(T), string reason = null)
|
||||||
|
{
|
||||||
|
return new GetResponse<T>(successful, val, reason);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
133
Wabbajack.Common/Extensions/HashHelper.cs
Normal file
133
Wabbajack.Common/Extensions/HashHelper.cs
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Taken from: http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode
|
||||||
|
*/
|
||||||
|
namespace Wabbajack
|
||||||
|
{
|
||||||
|
public static class HashHelper
|
||||||
|
{
|
||||||
|
public static int GetHashCode<T1, T2>(T1 arg1, T2 arg2)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
return 31 * (arg1 == null ? 0 : arg1.GetHashCode())
|
||||||
|
+ (arg2 == null ? 0 : arg2.GetHashCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = (arg1 == null ? 0 : arg1.GetHashCode());
|
||||||
|
hash = 31 * hash + (arg2 == null ? 0 : arg2.GetHashCode());
|
||||||
|
return 31 * hash + (arg3 == null ? 0 : arg3.GetHashCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetHashCode<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = (arg1 == null ? 0 : arg1.GetHashCode());
|
||||||
|
hash = 31 * hash + (arg2 == null ? 0 : arg2.GetHashCode());
|
||||||
|
hash = 31 * hash + (arg3 == null ? 0 : arg3.GetHashCode());
|
||||||
|
return 31 * hash + (arg4 == null ? 0 : arg4.GetHashCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetHashCode<T>(params T[] list)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
if (list == null) return hash;
|
||||||
|
for (int i = 0; i < list.Length; i++)
|
||||||
|
{
|
||||||
|
hash = 31 * hash + GetHashCode(list[i]);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetHashCode<T>(ReadOnlySpan<T> span)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
if (span == null) return hash;
|
||||||
|
for (int i = 0; i < span.Length; i++)
|
||||||
|
{
|
||||||
|
hash = 31 * hash + GetHashCode(span[i]);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetHashCode<T>(T t)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
return (t == null ? 0 : t.GetHashCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetHashCode<T>(IEnumerable<T> list)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
foreach (var item in list)
|
||||||
|
{
|
||||||
|
hash = 31 * hash + (item == null ? 0 : item.GetHashCode());
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a hashcode for a collection for that the order of items
|
||||||
|
/// does not matter.
|
||||||
|
/// So {1, 2, 3} and {3, 2, 1} will get same hash code.
|
||||||
|
/// </summary>
|
||||||
|
public static int GetHashCode_OrderBlind<T>(
|
||||||
|
IEnumerable<T> list)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
int count = 0;
|
||||||
|
foreach (var item in list)
|
||||||
|
{
|
||||||
|
hash += (item == null ? 0 : item.GetHashCode());
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return 31 * hash + count.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Alternative way to get a hashcode is to use a fluent
|
||||||
|
/// interface like this:<br />
|
||||||
|
/// return 0.CombineHashCode(field1).CombineHashCode(field2).
|
||||||
|
/// CombineHashCode(field3);
|
||||||
|
/// </summary>
|
||||||
|
public static int CombineHashCode<T>(this int hashCode, T arg)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
return CombineHashCode(hashCode, (arg == null ? 0 : arg.GetHashCode()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int CombineHashCode(this int hashCode, int rhsHash)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
return 31 * hashCode + rhsHash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -89,7 +89,10 @@
|
|||||||
<Compile Include="ChildProcessTracker.cs" />
|
<Compile Include="ChildProcessTracker.cs" />
|
||||||
<Compile Include="Consts.cs" />
|
<Compile Include="Consts.cs" />
|
||||||
<Compile Include="DynamicIniData.cs" />
|
<Compile Include="DynamicIniData.cs" />
|
||||||
|
<Compile Include="Error States\ErrorResponse.cs" />
|
||||||
|
<Compile Include="Error States\GetResponse.cs" />
|
||||||
<Compile Include="ExtensionManager.cs" />
|
<Compile Include="ExtensionManager.cs" />
|
||||||
|
<Compile Include="Extensions\HashHelper.cs" />
|
||||||
<Compile Include="FileExtractor.cs" />
|
<Compile Include="FileExtractor.cs" />
|
||||||
<Compile Include="GameMetaData.cs" />
|
<Compile Include="GameMetaData.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user