Skip to content

Commit

Permalink
Merge pull request #61 from Funkest/feature/funkest-guidv7-2
Browse files Browse the repository at this point in the history
add UUIDv7 generation option
  • Loading branch information
neuecc authored Nov 19, 2024
2 parents ad84e76 + 93a1835 commit 70c5af9
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 3 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ namespace UnitGenerator
{
this.Type = typeof(T);
this.Options = options;
  }
    }
}
}
#endif
}
```
Expand Down Expand Up @@ -283,11 +283,15 @@ public static bool operator false(Foo x) => !x.value;
public static bool operator !(Foo x) => !x.value;
```

> When type is Guid or [Ulid](https://github.com/Cysharp/Ulid), also implements `New()` and `New***()` static operator.
> When type is Guid or [Ulid](https://github.com/Cysharp/Ulid), also implements `New()` and `New***()` static operator.<br />
> For Guid type in .NET 9.0 or later, these methods accept an optional `uuidV7` parameter. When `uuidV7` is set to `true`, the methods use `Guid.CreateVersion7()` internally.
```csharp
public static GroupId New();
public static GroupId NewGroupId();
// overload .NET 9.0+
public static GroupId New(bool uuidV7);
public static GroupId NewGroupId(bool uuidV7);
```

Second parameter `UnitGenerateOptions options` can configure which method to implement, default is `None`.
Expand Down
7 changes: 7 additions & 0 deletions UnitGenerator.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileGenerate", "sandbox\Fil
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkApp", "src\EntityFrameworkApp\EntityFrameworkApp.csproj", "{51AE7857-4223-40FE-AEA9-F0E64C5F8238}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitGenerator.NET9.Tests", "tests\UnitGenerator.NET9.Tests\UnitGenerator.NET9.Tests.csproj", "{EAC3A025-E49B-4719-8738-9C3B67484A4A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -45,6 +47,10 @@ Global
{51AE7857-4223-40FE-AEA9-F0E64C5F8238}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51AE7857-4223-40FE-AEA9-F0E64C5F8238}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51AE7857-4223-40FE-AEA9-F0E64C5F8238}.Release|Any CPU.Build.0 = Release|Any CPU
{EAC3A025-E49B-4719-8738-9C3B67484A4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EAC3A025-E49B-4719-8738-9C3B67484A4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EAC3A025-E49B-4719-8738-9C3B67484A4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EAC3A025-E49B-4719-8738-9C3B67484A4A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -55,6 +61,7 @@ Global
{5DA06D43-A023-4464-B856-8BB42E8E4A05} = {187FBF64-D2AA-444D-AFB1-CE999BC6AD34}
{F8353A7A-290E-41D7-A6F8-8D8DBDD44433} = {34EB4113-923D-4855-979C-A0467461B75C}
{51AE7857-4223-40FE-AEA9-F0E64C5F8238} = {34EB4113-923D-4855-979C-A0467461B75C}
{EAC3A025-E49B-4719-8738-9C3B67484A4A} = {187FBF64-D2AA-444D-AFB1-CE999BC6AD34}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A64DF779-7829-414F-9E6E-3AF349486508}
Expand Down
12 changes: 12 additions & 0 deletions src/UnitGenerator/SourceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,18 @@ public bool TryFormat (Span<byte> utf8Destination, out int bytesWritten, ReadOnl
return new {{unitTypeName}}(Guid.NewGuid());
}
#if NET9_0_OR_GREATER
public static {{unitTypeName}} New(bool uuidV7)
{
return new {{unitTypeName}}(uuidV7 ? Guid.CreateVersion7() : Guid.NewGuid());
}
public static {{unitTypeName}} New{{unitTypeName}}(bool uuidV7)
{
return new {{unitTypeName}}(uuidV7 ? Guid.CreateVersion7() : Guid.NewGuid());
}
#endif
""");
}

Expand Down
25 changes: 25 additions & 0 deletions tests/UnitGenerator.NET9.Tests/UnitGenerator.NET9.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="FluentAssertions" Version="6.12.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\UnitGenerator\UnitGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

</Project>
35 changes: 35 additions & 0 deletions tests/UnitGenerator.NET9.Tests/UnitOfGuidTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using FluentAssertions;
using System;

namespace UnitGenerator.NET9.Tests;

public class UnitOfGuidTests
{
[Fact]
public void Guidv7_v4_Comparison_AsExpected()
{
// v7
TryGetUuidV7Timestamp(Guidv7Unit.New(uuidV7: true).AsPrimitive(), out var v).Should().BeTrue();
// ...approximate check
v?.ToString("yyyyMMdd").Should().Be(DateTime.UtcNow.ToString("yyyyMMdd"));
TryGetUuidV7Timestamp(Guidv7Unit.New().AsPrimitive(), out var _).Should().BeFalse();
}

static bool TryGetUuidV7Timestamp(Guid uuid, out DateTimeOffset? timestamp)
{
timestamp = null;
var uuidString = uuid.ToString("N");
// version number is the 13th character
if (uuidString[12] == '7')
{
var timestampHex = uuidString.Substring(0, 12);
var milliseconds = Convert.ToInt64(timestampHex, 16);
timestamp = DateTimeOffset.FromUnixTimeMilliseconds(milliseconds);
return true;
}
else return false;
}
}

[UnitOf<Guid>()]
public readonly partial struct Guidv7Unit { }

0 comments on commit 70c5af9

Please sign in to comment.