using System; using System.Diagnostics; using System.Globalization; using System.Runtime.CompilerServices; using System.Text; [assembly: InternalsVisibleTo("UnityEditor.CacheServerTests")] namespace UnityEditor.Build.CacheServer { internal static class Util { private const string IpAddressKey = "CacheServerIPAddress"; private static int ReverseByte(int b) { return ((b & 0x0F) << 4) | ((b >> 4) & 0x0F); } private static byte[] StringToByteArray(string input, bool asGuid) { var bytes = new byte[input.Length / 2]; for (var i = 0; i < input.Length; i += 2) { var b = Convert.ToByte(input.Substring(i, 2), 16); bytes[i / 2] = asGuid ? (byte)ReverseByte(b) : b; } return bytes; } /// /// Convert a hex string to a byte array that represents an Asset Hash /// /// 32 character hex string /// byte array public static byte[] StringToHash(string hashStr) { Debug.Assert(hashStr.Length == 32); return StringToByteArray(hashStr, false); } /// /// Convert a hex string to a byte array that represents an Asset GUID /// /// 32 character hex string /// byte array public static byte[] StringToGuid(string guidStr) { Debug.Assert(guidStr.Length == 32); return StringToByteArray(guidStr, true); } /// /// Parse an ascii byte array at start as an int value /// /// byte array /// offset /// public static int ReadUInt32(byte[] bytes, int index) { Debug.Assert(bytes.Length + index >= 8); return Int32.Parse(Encoding.ASCII.GetString(bytes, index, 8), NumberStyles.HexNumber); } /// /// Encode an integer as an ascii byte array /// /// integer /// true ensure the byte array is as short as possible; false to pad to 8 bytes /// public static byte[] EncodeInt32(int input, bool minLength = false) { return Encoding.ASCII.GetBytes(input.ToString(minLength ? "X" : "X8")); } /// /// Parse a subset of an ascii byte array as a long value /// /// byte array /// offset within to read from /// public static long ReadUInt64(byte[] bytes, int index) { Debug.Assert(bytes.Length + index >= 16); return Int64.Parse(Encoding.ASCII.GetString(bytes, index, 16), NumberStyles.HexNumber); } /// /// Encode a long value into an ascii byte array /// /// long value /// public static byte[] EncodeInt64(long input) { return Encoding.ASCII.GetBytes(input.ToString("X16")); } /// /// Compare two byte arrays for value equality /// /// first array /// second array /// public static bool ByteArraysAreEqual(byte[] ar1, byte[] ar2) { return ar1.Length == ar2.Length && ByteArraysAreEqual(ar1, 0, ar2, 0, ar1.Length); } /// /// Compare two byte arrays for value equality at specific offsets and length /// /// first array /// offset within first array /// second array /// offset within second array /// number of bytes to compare /// public static bool ByteArraysAreEqual(byte[] ar1, int start1, byte[] ar2, int start2, int count) { Debug.Assert(start1 >= 0 && start2 >= 0 && count >= 0); if (start1 + count > ar1.Length) return false; if (start2 + count > ar2.Length) return false; for (var i = 0; i < count; i++) if (ar1[start1 + i] != ar2[start2 + i]) return false; return true; } /// /// Retrieve the configured cache server address for the Unity Editor /// public static string ConfigCacheServerAddress { get { return EditorPrefs.GetString(IpAddressKey); } } /// /// Parse an address string in the format of 'address:port' to a string address and integer port number /// /// combined address string /// address part /// port part public static void ParseCacheServerIpAddress(string address, out string host, out int port) { host = null; port = 8126; var parts = address.Split(':'); if (parts.Length > 0) host = parts[0]; if (parts.Length > 1) port = int.Parse(parts[1]); } } }