wabbajack/Wabbajack.Hashing.xxHash64/Hash.cs

145 lines
3.2 KiB
C#
Raw Permalink Normal View History

2021-09-27 12:42:46 +00:00
using System;
using System.Buffers.Text;
2021-10-23 16:51:17 +00:00
namespace Wabbajack.Hashing.xxHash64;
public struct Hash : IEquatable<Hash>, IComparable<Hash>
2021-09-27 12:42:46 +00:00
{
2021-10-23 16:51:17 +00:00
private readonly ulong _code;
public Hash(ulong code = 0)
2021-09-27 12:42:46 +00:00
{
2021-10-23 16:51:17 +00:00
_code = code;
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public override string ToString()
{
return BitConverter.GetBytes(_code).ToBase64();
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public bool Equals(Hash other)
{
return _code == other._code;
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public int CompareTo(Hash other)
{
return _code.CompareTo(other._code);
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public override bool Equals(object? obj)
{
if (obj is Hash h)
return h._code == _code;
return false;
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public override int GetHashCode()
{
return (int) (_code >> 32) ^ (int) _code;
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static bool operator ==(Hash a, Hash b)
{
return a._code == b._code;
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static bool operator !=(Hash a, Hash b)
{
return !(a == b);
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static explicit operator ulong(Hash a)
{
return a._code;
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static explicit operator long(Hash a)
{
return BitConverter.ToInt64(BitConverter.GetBytes(a._code));
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public string ToBase64()
{
Span<byte> bytes = stackalloc byte[8];
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
BitConverter.TryWriteBytes(bytes, _code);
return Convert.ToBase64String(bytes);
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static Hash FromBase64(string hash)
{
return new Hash(BitConverter.ToUInt64(hash.FromBase64()));
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static Hash FromBase64(ReadOnlySpan<byte> data)
{
unsafe
2021-09-27 12:42:46 +00:00
{
2021-10-23 16:51:17 +00:00
Span<byte> buffer = stackalloc byte[12];
Base64.DecodeFromUtf8(data, buffer, out var consumed, out var written);
return new Hash(BitConverter.ToUInt64(buffer));
2021-09-27 12:42:46 +00:00
}
2021-10-23 16:51:17 +00:00
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public void ToBase64(Span<byte> output)
{
unsafe
2021-09-27 12:42:46 +00:00
{
2021-10-23 16:51:17 +00:00
Span<byte> buffer = stackalloc byte[8];
if (!BitConverter.TryWriteBytes(buffer, _code))
throw new Exception("Base64 Encoding error");
Base64.EncodeToUtf8(buffer, output, out var consumed, out var written);
2021-09-27 12:42:46 +00:00
}
2021-10-23 16:51:17 +00:00
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static Hash FromLong(in long argHash)
{
return new Hash(BitConverter.ToUInt64(BitConverter.GetBytes(argHash)));
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static Hash FromULong(in ulong argHash)
{
return new Hash(argHash);
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static Hash FromHex(string xxHashAsHex)
{
return new Hash(BitConverter.ToUInt64(xxHashAsHex.FromHex()));
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public string ToHex()
{
return BitConverter.GetBytes(_code).ToHex();
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public byte[] ToArray()
{
return BitConverter.GetBytes(_code);
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static Hash Interpret(string input)
{
return input.Length switch
2021-09-27 12:42:46 +00:00
{
2021-10-23 16:51:17 +00:00
16 => FromHex(input),
12 when input.EndsWith('=') => FromBase64(input),
_ => FromLong(long.Parse(input))
};
}
2021-09-27 12:42:46 +00:00
2021-10-23 16:51:17 +00:00
public static bool TryGetFromHex(string hex, out Hash hash)
{
hash = default;
if (hex.Length != 16) return false;
try
2021-09-27 12:42:46 +00:00
{
2021-10-23 16:51:17 +00:00
hash = FromHex(hex);
return true;
2021-09-27 12:42:46 +00:00
}
2021-10-23 16:51:17 +00:00
catch (Exception)
2021-09-27 12:42:46 +00:00
{
2021-10-23 16:51:17 +00:00
return false;
2021-09-27 12:42:46 +00:00
}
}
}