using System; using System.Runtime.InteropServices; using System.Text; using UnityEngine; namespace RoR2; [Serializable] [StructLayout(LayoutKind.Sequential, Pack = 8)] public struct Sha256Hash : IEquatable { [SerializeField] private ulong _00_07; [SerializeField] private ulong _08_15; [SerializeField] private ulong _16_23; [SerializeField] private ulong _24_31; private static readonly byte[] ulongToByteBuffer = new byte[8]; public static Sha256Hash FromHexString(string hexString, int startIndex = 0) { if (startIndex + hexString.Length < 64) { throw new ArgumentException("Not enough characters in string."); } int readPos = startIndex; ulong num = ReadULong(); ulong num2 = ReadULong(); ulong num3 = ReadULong(); ulong num4 = ReadULong(); return FromULong4(num, num2, num3, num4); byte ReadByte() { byte num5 = ReadNibble(); byte b = ReadNibble(); return (byte)((num5 << 4) | b); } byte ReadNibble() { char c = hexString[readPos++]; if (c >= '0' && c <= '9') { return (byte)(c - 48); } if (c >= 'a' && c <= 'f') { return (byte)(10 + (c - 97)); } if (c >= 'A' && c <= 'F') { return (byte)(10 + (c - 65)); } return 0; } ulong ReadULong() { ulongToByteBuffer[0] = ReadByte(); ulongToByteBuffer[1] = ReadByte(); ulongToByteBuffer[2] = ReadByte(); ulongToByteBuffer[3] = ReadByte(); ulongToByteBuffer[4] = ReadByte(); ulongToByteBuffer[5] = ReadByte(); ulongToByteBuffer[6] = ReadByte(); ulongToByteBuffer[7] = ReadByte(); return BitConverter.ToUInt64(ulongToByteBuffer, 0); } } public static Sha256Hash FromULong4(ulong _00_07, ulong _08_15, ulong _16_23, ulong _24_31) { Sha256Hash result = default(Sha256Hash); result._00_07 = _00_07; result._08_15 = _08_15; result._16_23 = _16_23; result._24_31 = _24_31; return result; } public void ToULong4(out ulong _00_07, out ulong _08_15, out ulong _16_23, out ulong _24_31) { _00_07 = this._00_07; _08_15 = this._08_15; _16_23 = this._16_23; _24_31 = this._24_31; } public static Sha256Hash FromBytes(byte[] bytes, int startIndex = 0) { if (startIndex + bytes.Length < 32) { throw new ArgumentException("Not enough bytes in buffer."); } Sha256Hash result = default(Sha256Hash); result._00_07 = BitConverter.ToUInt64(bytes, startIndex); result._08_15 = BitConverter.ToUInt64(bytes, startIndex + 8); result._16_23 = BitConverter.ToUInt64(bytes, startIndex + 16); result._24_31 = BitConverter.ToUInt64(bytes, startIndex + 24); return result; } public bool Equals(Sha256Hash other) { if (_00_07 == other._00_07 && _08_15 == other._08_15 && _16_23 == other._16_23) { return _24_31 == other._24_31; } return false; } public override bool Equals(object obj) { if (obj is Sha256Hash other) { return Equals(other); } return false; } public override int GetHashCode() { return (((((_00_07.GetHashCode() * 397) ^ _08_15.GetHashCode()) * 397) ^ _16_23.GetHashCode()) * 397) ^ _24_31.GetHashCode(); } public static StringBuilder AppendSha256HashHex(StringBuilder stringBuilder, in Sha256Hash hash) { stringBuilder.EnsureCapacity(stringBuilder.Length + 64); AppendULong(hash._00_07); AppendULong(hash._08_15); AppendULong(hash._16_23); AppendULong(hash._24_31); return stringBuilder; void AppendULong(ulong value) { stringBuilder.AppendByteHexValue((byte)(value & 0xFF)); stringBuilder.AppendByteHexValue((byte)((value >> 8) & 0xFF)); stringBuilder.AppendByteHexValue((byte)((value >> 16) & 0xFF)); stringBuilder.AppendByteHexValue((byte)((value >> 24) & 0xFF)); stringBuilder.AppendByteHexValue((byte)((value >> 32) & 0xFF)); stringBuilder.AppendByteHexValue((byte)((value >> 40) & 0xFF)); stringBuilder.AppendByteHexValue((byte)((value >> 48) & 0xFF)); stringBuilder.AppendByteHexValue((byte)((value >> 56) & 0xFF)); } } public override string ToString() { return AppendSha256HashHex(new StringBuilder(64), in this).ToString(); } }