Skip to content

Commit e5d9a28

Browse files
authored
Merge pull request #132 from whitecat346/feature/uuid
refactor(uuid): 重构Uuid生成实现
2 parents 151835e + 551a402 commit e5d9a28

File tree

3 files changed

+78
-10
lines changed

3 files changed

+78
-10
lines changed

PCL.Neo.Core/PCL.Neo.Core.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<TargetFramework>net9.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
7+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
78
</PropertyGroup>
89

910
<ItemGroup>
@@ -25,6 +26,7 @@
2526

2627
<ItemGroup>
2728
<PackageReference Include="System.Runtime.InteropServices" Version="4.3.0" />
29+
<PackageReference Include="Uuids" Version="2.0.0" />
2830
</ItemGroup>
2931

3032
</Project>

PCL.Neo.Core/Utils/Uuid.cs

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,64 @@
1+
using System.Security.Cryptography;
2+
using System.Text;
13
using System.Text.RegularExpressions;
24

35
namespace PCL.Neo.Core.Utils;
46

57
public static partial class Uuid // TODO: implement different way of genereate uuid
68
{
7-
private const string DefaultUuid = "00000000-0000-0000-0000-000000000000";
9+
public enum UuidGenerateType
10+
{
11+
Guid,
12+
Standard,
13+
MurmurHash3
14+
}
815

9-
public static string GenerateOfflineUuid(string username)
16+
/// <summary>
17+
/// Generate UUID base on input username. If username is empty or invalid,
18+
/// throw <see cref="ArgumentException"/>.
19+
/// </summary>
20+
/// <param name="username">Username to generate UUID.</param>
21+
/// <param name="type">Type of UUID generation.</param>
22+
/// <returns>Generated UUID.</returns>
23+
/// <exception cref="ArgumentException">
24+
/// If <paramref name="username"/> is invalid or empty.
25+
/// </exception>
26+
public static string GenerateUuid(string username, UuidGenerateType type)
1027
{
11-
if (string.IsNullOrEmpty(username) || !IsValidUsername(username))
12-
return DefaultUuid;
13-
var guid = new Guid(MurmurHash3.Hash(username));
14-
return guid.ToString();
28+
if (string.IsNullOrEmpty(username) ||
29+
!IsValidUsername(username))
30+
{
31+
throw new ArgumentException("Username is invalid.");
32+
}
33+
34+
var fullName = $"OfflinePlayer:{username}";
35+
36+
var uuid = type switch
37+
{
38+
UuidGenerateType.Guid => new Guid(MD5.HashData(Encoding.UTF8.GetBytes(fullName))).ToString(),
39+
UuidGenerateType.Standard => StadardVer(fullName),
40+
UuidGenerateType.MurmurHash3 => new Guid(MurmurHash3.Hash(fullName)).ToString(),
41+
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
42+
};
43+
44+
uuid = uuid.Replace("-", string.Empty);
45+
46+
return uuid;
1547
}
1648

49+
private static string StadardVer(string name)
50+
{
51+
var hash = MD5.HashData(Encoding.UTF8.GetBytes(name));
52+
53+
hash[6] = (byte)((hash[6] & 0x0F) | 0x30); // Version 3
54+
hash[8] = (byte)((hash[8] & 0x3F) | 0x80); // Variant 1 (RFC 4122)
55+
56+
return new Uuids.Uuid(hash).ToString();
57+
}
58+
59+
[GeneratedRegex("^[a-zA-Z0-9_]+$")]
60+
private static partial Regex ValidUsernameRegex();
61+
1762
public static bool IsValidUsername(string username)
1863
{
1964
return !string.IsNullOrEmpty(username) &&
@@ -22,11 +67,12 @@ public static bool IsValidUsername(string username)
2267
}
2368

2469
// MurmurHash3算法实现
70+
2571
private static class MurmurHash3
2672
{
2773
public static byte[] Hash(string str)
2874
{
29-
var bytes = System.Text.Encoding.UTF8.GetBytes(str);
75+
var bytes = Encoding.UTF8.GetBytes(str);
3076
const uint seed = 144;
3177
const uint c1 = 0xcc9e2d51;
3278
const uint c2 = 0x1b873593;
@@ -80,7 +126,4 @@ private static uint Fmix(uint h)
80126
return h;
81127
}
82128
}
83-
84-
[GeneratedRegex("^[a-zA-Z0-9_]+$")]
85-
private static partial Regex ValidUsernameRegex();
86129
}

PCL.Neo.Tests/Utils/UuidTest.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using PCL.Neo.Core.Utils;
2+
using System;
3+
4+
namespace PCL.Neo.Tests.Utils
5+
{
6+
[TestFixture]
7+
[TestOf(typeof(Uuid))]
8+
public class UuidTest
9+
{
10+
[Test]
11+
public void UuidGenerateTest()
12+
{
13+
var name = "WhiteCat";
14+
var uuid1 = Uuid.GenerateUuid(name, Uuid.UuidGenerateType.Guid);
15+
var uuid2 = Uuid.GenerateUuid(name, Uuid.UuidGenerateType.Standard);
16+
var uuid3 = Uuid.GenerateUuid(name, Uuid.UuidGenerateType.MurmurHash3);
17+
18+
Console.WriteLine(uuid1);
19+
Console.WriteLine(uuid2);
20+
Console.WriteLine(uuid3);
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)