File: Uuid.cs
Web Access
Project: ..\..\..\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;
    }
}