Skip to content
This repository has been archived by the owner on Dec 3, 2024. It is now read-only.

Commit

Permalink
feat!: Created solution and added implementation (#1)
Browse files Browse the repository at this point in the history
* feat: Created solution and added implementation

* chore: Added solution items to the solution

* chore: Implementation and documentation
  • Loading branch information
samtrion authored Apr 2, 2024
1 parent 18dd7da commit 11544a0
Show file tree
Hide file tree
Showing 11 changed files with 332 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ jobs:
dotnet-logging: ${{ inputs.dotnet-logging }}
dotnet-version: |
7.x
solution: ###SOLUTION###
solution: ./SequentialGuid.sln
secrets: inherit
23 changes: 9 additions & 14 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
<Project>

<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>

<ItemGroup>
<GlobalPackageReference Include="CSharpier.MSBuild" Version="0.26.3" />
<GlobalPackageReference Include="CSharpier.MSBuild" Version="0.27.3" />
<GlobalPackageReference Include="GitVersion.MsBuild" Version="5.12.0" />
<GlobalPackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" />
<GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.8.14" />
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="9.16.0.82469" Condition=" '$(BuildingInsideVisualStudio)' == 'true' " />
<GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.9.28" />
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="9.23.0.88079" Condition=" '$(BuildingInsideVisualStudio)' == 'true' " />
</ItemGroup>

<ItemGroup>
<PackageVersion Include="coverlet.collector" Version="6.0.0" />
<PackageVersion Include="coverlet.msbuild" Version="6.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="coverlet.msbuild" Version="6.0.2" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageVersion Include="NetEvolve.Extensions.XUnit" Version="2.0.36" />
<PackageVersion Include="Verify.Xunit" Version="22.5.0" />
<PackageVersion Include="xunit" Version="2.6.2" />
<PackageVersion Include="xunit.core" Version="2.6.2" />
<PackageVersion Include="xunit.runner.console" Version="2.6.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.4" />
<PackageVersion Include="xunit" Version="2.7.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7" />
</ItemGroup>

</Project>
36 changes: 34 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,34 @@
# template-dotnet
.NET template for repositories
# NetEvolve.SequentialGuid

[![Nuget](https://img.shields.io/nuget/v/NetEvolve.SequentialGuid?logo=nuget)](https://www.nuget.org/packages/NetEvolve.SequentialGuid/)
[![Nuget](https://img.shields.io/nuget/dt/NetEvolve.SequentialGuid?logo=nuget)](https://www.nuget.org/packages/NetEvolve.SequentialGuid/)


A .NET library to generate sequential GUIDs, similar to SQL Server's `newsequentialid()`.
It's a drop-in replacement for `System.Guid.NewGuid()`, focusing on performance and low allocation.

> [!CAUTION]
> The downside is that it's not as unique as `System.Guid.NewGuid()` and crypotographically insecure.
> So be sure to understand the trade-offs before using it.
## Features
With the `SequentialGuidType` enum, you can choose between 3 different types of sequential GUIDs:
- `AsBinary`<br/>The sequential part is at the beginning of the GUID, similar to Oracle's `SYS_GUID()`.
- `AsString` (Default)<br/>The sequential part is at the beginning of the GUID.
- `AtEnd`<br/>The sequential part is at the end of the GUID, similar to SQL Server's `newsequentialid()`.

## Installation

```pwsh
dotnet add package NetEvolve.SequentialGuid
```

## Usage

```csharp
using NetEvolve.SequentialGuid;

Guid guid = SequentialGuidFactory.NewGuid(); // Default is SequentialGuidType.AsString
// or
Guid guid = SequentialGuidFactory.NewGuid(SequentialGuidType.AsBinary);
```
57 changes: 57 additions & 0 deletions SequentialGuid.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{554192CF-0D2E-42CE-9EC7-066A8FD73A4F}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.filenesting.json = .filenesting.json
.gitignore = .gitignore
.gitmodules = .gitmodules
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
Directory.Packages.props = Directory.Packages.props
Directory.Solution.props = Directory.Solution.props
GitVersion.yml = GitVersion.yml
LICENSE = LICENSE
new-project.ps1 = new-project.ps1
nuget.config = nuget.config
README.md = README.md
update-solution.ps1 = update-solution.ps1
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{42F47CC9-30FA-44A2-91AC-3C55EB20D93E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0EAC5BD7-1E8D-4BA8-B0C9-19766031C329}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetEvolve.SequentialGuid", "src\NetEvolve.SequentialGuid\NetEvolve.SequentialGuid.csproj", "{ADAE52D0-CA16-4E3F-814D-65625111ED5A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetEvolve.SequentialGuid.Tests.Unit", "tests\NetEvolve.SequentialGuid.Tests.Unit\NetEvolve.SequentialGuid.Tests.Unit.csproj", "{433C0DEC-2E6F-4D22-9382-1BAA60BBBC0B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ADAE52D0-CA16-4E3F-814D-65625111ED5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ADAE52D0-CA16-4E3F-814D-65625111ED5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADAE52D0-CA16-4E3F-814D-65625111ED5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADAE52D0-CA16-4E3F-814D-65625111ED5A}.Release|Any CPU.Build.0 = Release|Any CPU
{433C0DEC-2E6F-4D22-9382-1BAA60BBBC0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{433C0DEC-2E6F-4D22-9382-1BAA60BBBC0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{433C0DEC-2E6F-4D22-9382-1BAA60BBBC0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{433C0DEC-2E6F-4D22-9382-1BAA60BBBC0B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{ADAE52D0-CA16-4E3F-814D-65625111ED5A} = {42F47CC9-30FA-44A2-91AC-3C55EB20D93E}
{433C0DEC-2E6F-4D22-9382-1BAA60BBBC0B} = {0EAC5BD7-1E8D-4BA8-B0C9-19766031C329}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4646205D-074A-48BC-9847-3262718F7FCD}
EndGlobalSection
EndGlobal
2 changes: 1 addition & 1 deletion new-project.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ New-Project `
-DisableTests $DisableTests `
-DisableUnitTests $DisableUnitTests `
-DisableIntegrationTests $DisableIntegrationTests `
-SolutionFile "###SOLUTION###" `
-SolutionFile "./SequentialGuid.sln" `
-OutputDirectory (Get-Location) `
-EnableProjectGrouping $EnableProjectGrouping `
-DisableArchitectureTests $DisableArchitectureTests
17 changes: 0 additions & 17 deletions new-solution.ps1

This file was deleted.

15 changes: 15 additions & 0 deletions src/NetEvolve.SequentialGuid/NetEvolve.SequentialGuid.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
<Title>$(MSBuildProjectName)</Title>
<Description>Small project for the generation of sequential Guids.</Description>
<PackageProjectUrl>https://github.com/dailydevops/sequentialguid</PackageProjectUrl>
<RepositoryUrl>https://github.com/dailydevops/sequentialguid.git</RepositoryUrl>
<PackageTags>sequentialguid;guid;uuid</PackageTags>
</PropertyGroup>

</Project>
65 changes: 65 additions & 0 deletions src/NetEvolve.SequentialGuid/SequentialGuidFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
namespace NetEvolve.SequentialGuid;

using System;
using System.Diagnostics.CodeAnalysis;

/// <summary>
/// Factory class to create sequential <see cref="Guid"/>s.
/// </summary>
public static class SequentialGuidFactory
{
/// <summary>
/// Creates a new sequential <see cref="Guid"/> based on <paramref name="sequentialGuid"/>.
/// </summary>
/// <param name="sequentialGuid">Optional parameter. Defines the characteristics of the Sequential Guid.</param>
/// <returns>A sequential <see cref="Guid"/>.</returns>
public static Guid NewGuid(SequentialGuidType sequentialGuid = SequentialGuidType.AsString) =>
NewGuid(Random.Shared, DateTimeOffset.UtcNow, sequentialGuid);

/// <summary>
/// Creates a new sequential <see cref="Guid"/> based on <paramref name="sequentialGuid"/>.
/// </summary>
/// <param name="random"></param>
/// <param name="utcNow"></param>
/// <param name="sequentialGuid">Optional parameter. Defines the characteristics of the Sequential Guid.</param>
/// <returns>A sequential <see cref="Guid"/>.</returns>
[SuppressMessage("Security", "CA5394:Do not use insecure randomness")]
internal static Guid NewGuid(
[NotNull] Random random,
DateTimeOffset utcNow,
SequentialGuidType sequentialGuid = SequentialGuidType.AsString
)
{
ArgumentNullException.ThrowIfNull(random);

var timeStamp = utcNow.Ticks / 10000L;
var timeStampBytes = BitConverter.GetBytes(timeStamp).AsSpan();

if (BitConverter.IsLittleEndian)
{
timeStampBytes.Reverse();
}

Span<byte> guidBytes = stackalloc byte[16];

if (sequentialGuid == SequentialGuidType.AtEnd)
{
timeStampBytes[2..8].CopyTo(guidBytes[10..16]);
random.NextBytes(guidBytes[..9]);

return new Guid(guidBytes);
}

timeStampBytes[2..8].CopyTo(guidBytes[..6]);

if (sequentialGuid == SequentialGuidType.AsString && BitConverter.IsLittleEndian)
{
guidBytes[..4].Reverse();
guidBytes[4..6].Reverse();
}

random.NextBytes(guidBytes[7..]);

return new Guid(guidBytes);
}
}
33 changes: 33 additions & 0 deletions src/NetEvolve.SequentialGuid/SequentialGuidType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace NetEvolve.SequentialGuid;

using System;

/// <summary>
/// Describes the position of the sequential part of the <see cref="Guid"/>.
/// </summary>
public enum SequentialGuidType
{
/// <summary>
/// The sequential part is at the beginning of the <see cref="Guid"/>.
/// </summary>
/// <remarks>
/// Used by Oracle.
/// </remarks>
AsBinary = 1,

/// <summary>
/// The sequential part is at the beginning of the <see cref="Guid"/>.
/// </summary>
/// <remarks>
/// Used by MySql and PostgreSql.
/// </remarks>
AsString = 0,

/// <summary>
/// The sequential part is at the end of the <see cref="Guid"/>.
/// </summary>
/// <remarks>
/// Used by SqlServer.
/// </remarks>
AtEnd = 2,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.msbuild" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="NetEvolve.Extensions.XUnit" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\NetEvolve.SequentialGuid\NetEvolve.SequentialGuid.csproj" />
</ItemGroup>

</Project>
Loading

0 comments on commit 11544a0

Please sign in to comment.