| File: Uuid.cs | Web Access |
| Project: src\sdk\src\Cli\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj (Microsoft.DotNet.Cli.Utils) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.IO.Hashing; namespace Microsoft.DotNet.Cli.Utils; public class Uuid { /// <summary> /// Generate a Version 8 (XxHash3 Name Based) Guid from a name. /// </summary> /// <param name="name">The name to use for generating the GUID.</param> /// <returns>A generated <see cref="GUID"/>.</returns> public static Guid Create(string name) { // Any fixed GUID will do for a namespace. Guid namespaceId = new("28F1468D-672B-489A-8E0C-7C5B3030630C"); var nameBytes = Encoding.UTF8.GetBytes(name ?? string.Empty); var namespaceBytes = namespaceId.ToByteArray(); SwapGuidByteOrder(namespaceBytes); var streamToHash = new byte[namespaceBytes.Length + nameBytes.Length]; Array.Copy(namespaceBytes, streamToHash, namespaceBytes.Length); Array.Copy(nameBytes, 0, streamToHash, namespaceBytes.Length, nameBytes.Length); var hashResult = XxHash128.Hash(streamToHash); // This is just used for generating a named pipe so we don't need a cryptographic hash Debug.Assert(hashResult.Length >= 16); var res = new byte[16]; Array.Copy(hashResult, res, res.Length); unchecked { res[6] = (byte)(0x80 | (res[6] & 0x0F)); } unchecked { res[8] = (byte)(0x40 | (res[8] & 0x3F)); } SwapGuidByteOrder(res); return new Guid(res); } // Do a byte order swap, .NET GUIDs store multi byte components in little // endian. private static void SwapGuidByteOrder(byte[] b) { Swap(b, 0, 3); Swap(b, 1, 2); Swap(b, 5, 6); Swap(b, 7, 8); } private static void Swap(byte[] b, int x, int y) { byte t = b[x]; b[x] = b[y]; b[y] = t; } }