diff --git a/.gitignore b/.gitignore
index c79b456..8c0a52c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,9 @@
# SourceGenerator Launch Settings
src/CompositeKey.SourceGeneration/Properties/launchSettings.json
+# BenchmarkDotNet
+BenchmarkDotNet.Artifacts/
+
# Verify snapshot testing
*.received.*
diff --git a/CLAUDE.md b/CLAUDE.md
index 0fcb78e..9aa41cf 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -59,6 +59,14 @@ The solution is split into four main projects plus corresponding test projects:
- **Central Package Management**: via `Directory.Packages.props`
- Analyzer projects target both `net8.0` and `netstandard2.0`
+## Benchmarks
+
+**CompositeKey.Benchmarks** (`src/CompositeKey.Benchmarks/`) — BenchmarkDotNet benchmarks for generated code performance. Manual, developer-run (not part of CI). Covers `ToString`, `Parse`, `TryParse`, and partition/sort key methods across representative key types exercising all major code-generation paths.
+
+```bash
+dotnet run -c Release --project src/CompositeKey.Benchmarks -- --filter "*"
+```
+
## Conventions
- Commit messages follow Conventional Commits (`feat:`, `fix:`, `perf:`, etc.) — GitVersion and `.versionrc` drive versioning and changelog
diff --git a/CompositeKey.slnx b/CompositeKey.slnx
index eaa09f0..c69dfb6 100644
--- a/CompositeKey.slnx
+++ b/CompositeKey.slnx
@@ -14,4 +14,7 @@
+
+
+
diff --git a/src/CompositeKey.Benchmarks/CompositeKey.Benchmarks.csproj b/src/CompositeKey.Benchmarks/CompositeKey.Benchmarks.csproj
new file mode 100644
index 0000000..1e9e5e5
--- /dev/null
+++ b/src/CompositeKey.Benchmarks/CompositeKey.Benchmarks.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net10.0;net9.0;net8.0
+ true
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CompositeKey.Benchmarks/FastPathEnumKeyBenchmarks.cs b/src/CompositeKey.Benchmarks/FastPathEnumKeyBenchmarks.cs
new file mode 100644
index 0000000..13799b4
--- /dev/null
+++ b/src/CompositeKey.Benchmarks/FastPathEnumKeyBenchmarks.cs
@@ -0,0 +1,35 @@
+using BenchmarkDotNet.Attributes;
+
+namespace CompositeKey.Benchmarks;
+
+///
+/// Fast-path enum key — exercises the generated enum helper fast path.
+///
+[CompositeKey("{GuidValue}#Constant#{EnumValue}@{StringValue}")]
+public sealed partial record FastPathEnumKey(Guid GuidValue, FastPathEnumKey.KeyEnumType EnumValue, string StringValue)
+{
+ public enum KeyEnumType { One, Two, Three, Four, Five, Six, Seven, Eight, Nine }
+}
+
+[MemoryDiagnoser]
+public class FastPathEnumKeyBenchmarks
+{
+ private FastPathEnumKey _key = null!;
+ private string _formatted = null!;
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ _key = new FastPathEnumKey(Guid.NewGuid(), FastPathEnumKey.KeyEnumType.Five, "test-value");
+ _formatted = _key.ToString();
+ }
+
+ [Benchmark]
+ public string ToString_FastPathEnumKey() => _key.ToString();
+
+ [Benchmark]
+ public FastPathEnumKey Parse_FastPathEnumKey() => FastPathEnumKey.Parse(_formatted);
+
+ [Benchmark]
+ public bool TryParse_FastPathEnumKey() => FastPathEnumKey.TryParse(_formatted, out _);
+}
diff --git a/src/CompositeKey.Benchmarks/GuidPrimaryKeyBenchmarks.cs b/src/CompositeKey.Benchmarks/GuidPrimaryKeyBenchmarks.cs
new file mode 100644
index 0000000..7a5d22d
--- /dev/null
+++ b/src/CompositeKey.Benchmarks/GuidPrimaryKeyBenchmarks.cs
@@ -0,0 +1,32 @@
+using BenchmarkDotNet.Attributes;
+
+namespace CompositeKey.Benchmarks;
+
+///
+/// Simple Guid primary key — exercises stackalloc split and Guid.TryParseExact parse path.
+///
+[CompositeKey("{First}#{Second}")]
+public sealed partial record GuidPrimaryKey(Guid First, Guid Second);
+
+[MemoryDiagnoser]
+public class GuidPrimaryKeyBenchmarks
+{
+ private GuidPrimaryKey _key = null!;
+ private string _formatted = null!;
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ _key = new GuidPrimaryKey(Guid.NewGuid(), Guid.NewGuid());
+ _formatted = _key.ToString();
+ }
+
+ [Benchmark]
+ public string ToString_GuidPrimaryKey() => _key.ToString();
+
+ [Benchmark]
+ public GuidPrimaryKey Parse_GuidPrimaryKey() => GuidPrimaryKey.Parse(_formatted);
+
+ [Benchmark]
+ public bool TryParse_GuidPrimaryKey() => GuidPrimaryKey.TryParse(_formatted, out _);
+}
diff --git a/src/CompositeKey.Benchmarks/MixedCompositeKeyBenchmarks.cs b/src/CompositeKey.Benchmarks/MixedCompositeKeyBenchmarks.cs
new file mode 100644
index 0000000..7bc4fed
--- /dev/null
+++ b/src/CompositeKey.Benchmarks/MixedCompositeKeyBenchmarks.cs
@@ -0,0 +1,46 @@
+using BenchmarkDotNet.Attributes;
+
+namespace CompositeKey.Benchmarks;
+
+///
+/// Mixed-type composite key with partition/sort separation — exercises string.Create with exact length,
+/// static lambda formatting, partition/sort splitting, and multi-type parsing.
+///
+[CompositeKey("{GuidValue}#{DecimalValue}|Constant~{EnumValue}@{StringValue}", PrimaryKeySeparator = '|')]
+public sealed partial record MixedCompositeKey(
+ Guid GuidValue,
+ decimal DecimalValue,
+ MixedCompositeKey.KeyEnumType EnumValue,
+ string StringValue)
+{
+ public enum KeyEnumType { One, Two, Three }
+}
+
+[MemoryDiagnoser]
+public class MixedCompositeKeyBenchmarks
+{
+ private MixedCompositeKey _key = null!;
+ private string _formatted = null!;
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ _key = new MixedCompositeKey(Guid.NewGuid(), 123.45m, MixedCompositeKey.KeyEnumType.Two, "test-value");
+ _formatted = _key.ToString();
+ }
+
+ [Benchmark]
+ public string ToString_MixedCompositeKey() => _key.ToString();
+
+ [Benchmark]
+ public string ToPartitionKeyString_MixedCompositeKey() => _key.ToPartitionKeyString();
+
+ [Benchmark]
+ public string ToSortKeyString_MixedCompositeKey() => _key.ToSortKeyString();
+
+ [Benchmark]
+ public MixedCompositeKey Parse_MixedCompositeKey() => MixedCompositeKey.Parse(_formatted);
+
+ [Benchmark]
+ public bool TryParse_MixedCompositeKey() => MixedCompositeKey.TryParse(_formatted, out _);
+}
diff --git a/src/CompositeKey.Benchmarks/Program.cs b/src/CompositeKey.Benchmarks/Program.cs
new file mode 100644
index 0000000..c9a0467
--- /dev/null
+++ b/src/CompositeKey.Benchmarks/Program.cs
@@ -0,0 +1,3 @@
+using BenchmarkDotNet.Running;
+
+BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
diff --git a/src/CompositeKey.Benchmarks/README.md b/src/CompositeKey.Benchmarks/README.md
new file mode 100644
index 0000000..b545fe7
--- /dev/null
+++ b/src/CompositeKey.Benchmarks/README.md
@@ -0,0 +1,47 @@
+# CompositeKey.Benchmarks
+
+Performance benchmarks for generated CompositeKey code using [BenchmarkDotNet](https://benchmarkdotnet.org/).
+
+These benchmarks are **manual, developer-run** and are **not** part of the CI test suite.
+
+## Running Benchmarks
+
+Run all benchmarks:
+
+```bash
+dotnet run -c Release --project src/CompositeKey.Benchmarks -- --filter "*"
+```
+
+Run a specific benchmark class:
+
+```bash
+dotnet run -c Release --project src/CompositeKey.Benchmarks -- --filter "*GuidPrimaryKeyBenchmarks*"
+```
+
+Run a specific benchmark method:
+
+```bash
+dotnet run -c Release --project src/CompositeKey.Benchmarks -- --filter "*ToString_GuidPrimaryKey*"
+```
+
+Target a specific TFM for cross-runtime comparison:
+
+```bash
+dotnet run -c Release --project src/CompositeKey.Benchmarks --framework net10.0 -- --filter "*"
+```
+
+## Interpreting Results
+
+BenchmarkDotNet produces a summary table with these key columns:
+
+| Column | Description |
+|----------------|------------------------------------------------------|
+| **Mean** | Average execution time per operation |
+| **Error** | Half of the 99.9% confidence interval |
+| **StdDev** | Standard deviation of measurements |
+| **Gen0** | Number of Gen 0 GC collections per 1000 operations |
+| **Allocated** | Heap memory allocated per operation (bytes) |
+
+Lower values are better for all columns. An `Allocated` value of `0 B` or `-` indicates a zero-allocation code path.
+
+Results are written to `BenchmarkDotNet.Artifacts/` which is git-ignored.
diff --git a/src/CompositeKey.Benchmarks/RepeatingCollectionKeyBenchmarks.cs b/src/CompositeKey.Benchmarks/RepeatingCollectionKeyBenchmarks.cs
new file mode 100644
index 0000000..9225c05
--- /dev/null
+++ b/src/CompositeKey.Benchmarks/RepeatingCollectionKeyBenchmarks.cs
@@ -0,0 +1,33 @@
+using BenchmarkDotNet.Attributes;
+
+namespace CompositeKey.Benchmarks;
+
+///
+/// Repeating collection key — exercises DefaultInterpolatedStringHandler formatting
+/// and variable-length stackalloc parsing.
+///
+[CompositeKey("{Type}#{Tags...,}")]
+public sealed partial record RepeatingCollectionKey(string Type, List Tags);
+
+[MemoryDiagnoser]
+public class RepeatingCollectionKeyBenchmarks
+{
+ private RepeatingCollectionKey _key = null!;
+ private string _formatted = null!;
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ _key = new RepeatingCollectionKey("entity", ["alpha", "beta", "gamma", "delta"]);
+ _formatted = _key.ToString();
+ }
+
+ [Benchmark]
+ public string ToString_RepeatingCollectionKey() => _key.ToString();
+
+ [Benchmark]
+ public RepeatingCollectionKey Parse_RepeatingCollectionKey() => RepeatingCollectionKey.Parse(_formatted);
+
+ [Benchmark]
+ public bool TryParse_RepeatingCollectionKey() => RepeatingCollectionKey.TryParse(_formatted, out _);
+}
diff --git a/src/CompositeKey.Benchmarks/RepeatingSpanParsableBenchmarks.cs b/src/CompositeKey.Benchmarks/RepeatingSpanParsableBenchmarks.cs
new file mode 100644
index 0000000..a32b4ee
--- /dev/null
+++ b/src/CompositeKey.Benchmarks/RepeatingSpanParsableBenchmarks.cs
@@ -0,0 +1,37 @@
+using System.Collections.Immutable;
+using BenchmarkDotNet.Attributes;
+
+namespace CompositeKey.Benchmarks;
+
+///
+/// Repeating SpanParsable key with same separator and ImmutableArray — exercises the same-separator
+/// parse path (variable part count from initial split), ImmutableArray.CreateRange() construction,
+/// and SpanParsable item parsing within the repeat loop.
+///
+[CompositeKey("NODES#{Scores...#}")]
+public sealed partial record RepeatingSpanParsableSameSeparatorKey(ImmutableArray Scores);
+
+[MemoryDiagnoser]
+public class RepeatingSpanParsableBenchmarks
+{
+ private RepeatingSpanParsableSameSeparatorKey _key = null!;
+ private string _formatted = null!;
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ _key = new RepeatingSpanParsableSameSeparatorKey([100, 200, 300, 400]);
+ _formatted = _key.ToString();
+ }
+
+ [Benchmark]
+ public string ToString_RepeatingSpanParsable() => _key.ToString();
+
+ [Benchmark]
+ public RepeatingSpanParsableSameSeparatorKey Parse_RepeatingSpanParsable() =>
+ RepeatingSpanParsableSameSeparatorKey.Parse(_formatted);
+
+ [Benchmark]
+ public bool TryParse_RepeatingSpanParsable() =>
+ RepeatingSpanParsableSameSeparatorKey.TryParse(_formatted, out _);
+}
diff --git a/src/CompositeKey.Benchmarks/packages.lock.json b/src/CompositeKey.Benchmarks/packages.lock.json
new file mode 100644
index 0000000..584fa70
--- /dev/null
+++ b/src/CompositeKey.Benchmarks/packages.lock.json
@@ -0,0 +1,535 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net10.0": {
+ "BenchmarkDotNet": {
+ "type": "Direct",
+ "requested": "[0.15.8, )",
+ "resolved": "0.15.8",
+ "contentHash": "paCfrWxSeHqn3rUZc0spYXVFnHCF0nzRhG0nOLnyTjZYs8spsimBaaNmb3vwqvALKIplbYq/TF393vYiYSnh/Q==",
+ "dependencies": {
+ "BenchmarkDotNet.Annotations": "0.15.8",
+ "CommandLineParser": "2.9.1",
+ "Gee.External.Capstone": "2.3.0",
+ "Iced": "1.21.0",
+ "Microsoft.CodeAnalysis.CSharp": "4.14.0",
+ "Microsoft.Diagnostics.Runtime": "3.1.512801",
+ "Microsoft.Diagnostics.Tracing.TraceEvent": "3.1.21",
+ "Microsoft.DotNet.PlatformAbstractions": "3.1.6",
+ "Perfolizer": "[0.6.1]",
+ "System.Management": "9.0.5"
+ }
+ },
+ "DotNet.ReproducibleBuilds": {
+ "type": "Direct",
+ "requested": "[1.2.39, )",
+ "resolved": "1.2.39",
+ "contentHash": "fcFN01tDTIQqDuTwr1jUQK/geofiwjG5DycJQOnC72i1SsLAk1ELe+apBOuZ11UMQG8YKFZG1FgvjZPbqHyatg=="
+ },
+ "BenchmarkDotNet.Annotations": {
+ "type": "Transitive",
+ "resolved": "0.15.8",
+ "contentHash": "hfucY0ycAsB0SsoaZcaAp9oq5wlWBJcylvEJb9pmvdYUx6PD6S4mDiYnZWjdjAlLhIpe/xtGCwzORfzAzPqvzA=="
+ },
+ "CommandLineParser": {
+ "type": "Transitive",
+ "resolved": "2.9.1",
+ "contentHash": "OE0sl1/sQ37bjVsPKKtwQlWDgqaxWgtme3xZz7JssWUzg5JpMIyHgCTY9MVMxOg48fJ1AgGT3tgdH5m/kQ5xhA=="
+ },
+ "Gee.External.Capstone": {
+ "type": "Transitive",
+ "resolved": "2.3.0",
+ "contentHash": "2ap/rYmjtzCOT8hxrnEW/QeiOt+paD8iRrIcdKX0cxVwWLFa1e+JDBNeECakmccXrSFeBQuu5AV8SNkipFMMMw=="
+ },
+ "Iced": {
+ "type": "Transitive",
+ "resolved": "1.21.0",
+ "contentHash": "dv5+81Q1TBQvVMSOOOmRcjJmvWcX3BZPZsIq31+RLc5cNft0IHAyNlkdb7ZarOWG913PyBoFDsDXoCIlKmLclg=="
+ },
+ "Microsoft.CodeAnalysis.Analyzers": {
+ "type": "Transitive",
+ "resolved": "3.11.0",
+ "contentHash": "v/EW3UE8/lbEYHoC2Qq7AR/DnmvpgdtAMndfQNmpuIMx/Mto8L5JnuCfdBYtgvalQOtfNCnxFejxuRrryvUTsg=="
+ },
+ "Microsoft.CodeAnalysis.Common": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "PC3tuwZYnC+idaPuoC/AZpEdwrtX7qFpmnrfQkgobGIWiYmGi5MCRtl5mx6QrfMGQpK78X2lfIEoZDLg/qnuHg==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0"
+ }
+ },
+ "Microsoft.CodeAnalysis.CSharp": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "568a6wcTivauIhbeWcCwfWwIn7UV7MeHEBvFB2uzGIpM2OhJ4eM/FZ8KS0yhPoNxnSpjGzz7x7CIjTxhslojQA==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0",
+ "Microsoft.CodeAnalysis.Common": "[4.14.0]"
+ }
+ },
+ "Microsoft.Diagnostics.NETCore.Client": {
+ "type": "Transitive",
+ "resolved": "0.2.510501",
+ "contentHash": "juoqJYMDs+lRrrZyOkXXMImJHneCF23cuvO4waFRd2Ds7j+ZuGIPbJm0Y/zz34BdeaGiiwGWraMUlln05W1PCQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "6.0.0"
+ }
+ },
+ "Microsoft.Diagnostics.Runtime": {
+ "type": "Transitive",
+ "resolved": "3.1.512801",
+ "contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==",
+ "dependencies": {
+ "Microsoft.Diagnostics.NETCore.Client": "0.2.410101"
+ }
+ },
+ "Microsoft.Diagnostics.Tracing.TraceEvent": {
+ "type": "Transitive",
+ "resolved": "3.1.21",
+ "contentHash": "/OrJFKaojSR6TkUKtwh8/qA9XWNtxLrXMqvEb89dBSKCWjaGVTbKMYodIUgF5deCEtmd6GXuRerciXGl5bhZ7Q==",
+ "dependencies": {
+ "Microsoft.Diagnostics.NETCore.Client": "0.2.510501",
+ "System.Reflection.TypeExtensions": "4.7.0"
+ }
+ },
+ "Microsoft.DotNet.PlatformAbstractions": {
+ "type": "Transitive",
+ "resolved": "3.1.6",
+ "contentHash": "jek4XYaQ/PGUwDKKhwR8K47Uh1189PFzMeLqO83mXrXQVIpARZCcfuDedH50YDTepBkfijCZN5U/vZi++erxtg=="
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "6.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
+ "Microsoft.Extensions.Options": "6.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA=="
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
+ "Microsoft.Extensions.Primitives": "6.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ=="
+ },
+ "Perfolizer": {
+ "type": "Transitive",
+ "resolved": "0.6.1",
+ "contentHash": "CR1QmWg4XYBd1Pb7WseP+sDmV8nGPwvmowKynExTqr3OuckIGVMhvmN4LC5PGzfXqDlR295+hz/T7syA1CxEqA==",
+ "dependencies": {
+ "Pragmastat": "3.2.4"
+ }
+ },
+ "Pragmastat": {
+ "type": "Transitive",
+ "resolved": "3.2.4",
+ "contentHash": "I5qFifWw/gaTQT52MhzjZpkm/JPlfjSeO/DTZJjO7+hTKI+0aGRgOgZ3NN6D96dDuuqbIAZSeA5RimtHjqrA2A=="
+ },
+ "System.CodeDom": {
+ "type": "Transitive",
+ "resolved": "9.0.5",
+ "contentHash": "cuzLM2MWutf9ZBEMPYYfd0DXwYdvntp7VCT6a/wvbKCa2ZuvGmW74xi+YBa2mrfEieAXqM4TNKlMmSnfAfpUoQ=="
+ },
+ "System.Management": {
+ "type": "Transitive",
+ "resolved": "9.0.5",
+ "contentHash": "n6o9PZm9p25+zAzC3/48K0oHnaPKTInRrxqFq1fi/5TPbMLjuoCm/h//mS3cUmSy+9AO1Z+qsC/Ilt/ZFatv5Q==",
+ "dependencies": {
+ "System.CodeDom": "9.0.5"
+ }
+ },
+ "System.Reflection.TypeExtensions": {
+ "type": "Transitive",
+ "resolved": "4.7.0",
+ "contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA=="
+ },
+ "compositekey": {
+ "type": "Project"
+ }
+ },
+ "net8.0": {
+ "BenchmarkDotNet": {
+ "type": "Direct",
+ "requested": "[0.15.8, )",
+ "resolved": "0.15.8",
+ "contentHash": "paCfrWxSeHqn3rUZc0spYXVFnHCF0nzRhG0nOLnyTjZYs8spsimBaaNmb3vwqvALKIplbYq/TF393vYiYSnh/Q==",
+ "dependencies": {
+ "BenchmarkDotNet.Annotations": "0.15.8",
+ "CommandLineParser": "2.9.1",
+ "Gee.External.Capstone": "2.3.0",
+ "Iced": "1.21.0",
+ "Microsoft.CodeAnalysis.CSharp": "4.14.0",
+ "Microsoft.Diagnostics.Runtime": "3.1.512801",
+ "Microsoft.Diagnostics.Tracing.TraceEvent": "3.1.21",
+ "Microsoft.DotNet.PlatformAbstractions": "3.1.6",
+ "Perfolizer": "[0.6.1]",
+ "System.Management": "9.0.5"
+ }
+ },
+ "DotNet.ReproducibleBuilds": {
+ "type": "Direct",
+ "requested": "[1.2.39, )",
+ "resolved": "1.2.39",
+ "contentHash": "fcFN01tDTIQqDuTwr1jUQK/geofiwjG5DycJQOnC72i1SsLAk1ELe+apBOuZ11UMQG8YKFZG1FgvjZPbqHyatg=="
+ },
+ "BenchmarkDotNet.Annotations": {
+ "type": "Transitive",
+ "resolved": "0.15.8",
+ "contentHash": "hfucY0ycAsB0SsoaZcaAp9oq5wlWBJcylvEJb9pmvdYUx6PD6S4mDiYnZWjdjAlLhIpe/xtGCwzORfzAzPqvzA=="
+ },
+ "CommandLineParser": {
+ "type": "Transitive",
+ "resolved": "2.9.1",
+ "contentHash": "OE0sl1/sQ37bjVsPKKtwQlWDgqaxWgtme3xZz7JssWUzg5JpMIyHgCTY9MVMxOg48fJ1AgGT3tgdH5m/kQ5xhA=="
+ },
+ "Gee.External.Capstone": {
+ "type": "Transitive",
+ "resolved": "2.3.0",
+ "contentHash": "2ap/rYmjtzCOT8hxrnEW/QeiOt+paD8iRrIcdKX0cxVwWLFa1e+JDBNeECakmccXrSFeBQuu5AV8SNkipFMMMw=="
+ },
+ "Iced": {
+ "type": "Transitive",
+ "resolved": "1.21.0",
+ "contentHash": "dv5+81Q1TBQvVMSOOOmRcjJmvWcX3BZPZsIq31+RLc5cNft0IHAyNlkdb7ZarOWG913PyBoFDsDXoCIlKmLclg=="
+ },
+ "Microsoft.CodeAnalysis.Analyzers": {
+ "type": "Transitive",
+ "resolved": "3.11.0",
+ "contentHash": "v/EW3UE8/lbEYHoC2Qq7AR/DnmvpgdtAMndfQNmpuIMx/Mto8L5JnuCfdBYtgvalQOtfNCnxFejxuRrryvUTsg=="
+ },
+ "Microsoft.CodeAnalysis.Common": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "PC3tuwZYnC+idaPuoC/AZpEdwrtX7qFpmnrfQkgobGIWiYmGi5MCRtl5mx6QrfMGQpK78X2lfIEoZDLg/qnuHg==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0",
+ "System.Collections.Immutable": "9.0.0",
+ "System.Reflection.Metadata": "9.0.0"
+ }
+ },
+ "Microsoft.CodeAnalysis.CSharp": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "568a6wcTivauIhbeWcCwfWwIn7UV7MeHEBvFB2uzGIpM2OhJ4eM/FZ8KS0yhPoNxnSpjGzz7x7CIjTxhslojQA==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0",
+ "Microsoft.CodeAnalysis.Common": "[4.14.0]",
+ "System.Collections.Immutable": "9.0.0",
+ "System.Reflection.Metadata": "9.0.0"
+ }
+ },
+ "Microsoft.Diagnostics.NETCore.Client": {
+ "type": "Transitive",
+ "resolved": "0.2.510501",
+ "contentHash": "juoqJYMDs+lRrrZyOkXXMImJHneCF23cuvO4waFRd2Ds7j+ZuGIPbJm0Y/zz34BdeaGiiwGWraMUlln05W1PCQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "6.0.0"
+ }
+ },
+ "Microsoft.Diagnostics.Runtime": {
+ "type": "Transitive",
+ "resolved": "3.1.512801",
+ "contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==",
+ "dependencies": {
+ "Microsoft.Diagnostics.NETCore.Client": "0.2.410101"
+ }
+ },
+ "Microsoft.Diagnostics.Tracing.TraceEvent": {
+ "type": "Transitive",
+ "resolved": "3.1.21",
+ "contentHash": "/OrJFKaojSR6TkUKtwh8/qA9XWNtxLrXMqvEb89dBSKCWjaGVTbKMYodIUgF5deCEtmd6GXuRerciXGl5bhZ7Q==",
+ "dependencies": {
+ "Microsoft.Diagnostics.NETCore.Client": "0.2.510501"
+ }
+ },
+ "Microsoft.DotNet.PlatformAbstractions": {
+ "type": "Transitive",
+ "resolved": "3.1.6",
+ "contentHash": "jek4XYaQ/PGUwDKKhwR8K47Uh1189PFzMeLqO83mXrXQVIpARZCcfuDedH50YDTepBkfijCZN5U/vZi++erxtg=="
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "6.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
+ "Microsoft.Extensions.Options": "6.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA=="
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
+ "Microsoft.Extensions.Primitives": "6.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ=="
+ },
+ "Perfolizer": {
+ "type": "Transitive",
+ "resolved": "0.6.1",
+ "contentHash": "CR1QmWg4XYBd1Pb7WseP+sDmV8nGPwvmowKynExTqr3OuckIGVMhvmN4LC5PGzfXqDlR295+hz/T7syA1CxEqA==",
+ "dependencies": {
+ "Pragmastat": "3.2.4"
+ }
+ },
+ "Pragmastat": {
+ "type": "Transitive",
+ "resolved": "3.2.4",
+ "contentHash": "I5qFifWw/gaTQT52MhzjZpkm/JPlfjSeO/DTZJjO7+hTKI+0aGRgOgZ3NN6D96dDuuqbIAZSeA5RimtHjqrA2A=="
+ },
+ "System.CodeDom": {
+ "type": "Transitive",
+ "resolved": "9.0.5",
+ "contentHash": "cuzLM2MWutf9ZBEMPYYfd0DXwYdvntp7VCT6a/wvbKCa2ZuvGmW74xi+YBa2mrfEieAXqM4TNKlMmSnfAfpUoQ=="
+ },
+ "System.Collections.Immutable": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "QhkXUl2gNrQtvPmtBTQHb0YsUrDiDQ2QS09YbtTTiSjGcf7NBqtYbrG/BE06zcBPCKEwQGzIv13IVdXNOSub2w=="
+ },
+ "System.Management": {
+ "type": "Transitive",
+ "resolved": "9.0.5",
+ "contentHash": "n6o9PZm9p25+zAzC3/48K0oHnaPKTInRrxqFq1fi/5TPbMLjuoCm/h//mS3cUmSy+9AO1Z+qsC/Ilt/ZFatv5Q==",
+ "dependencies": {
+ "System.CodeDom": "9.0.5"
+ }
+ },
+ "System.Reflection.Metadata": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "ANiqLu3DxW9kol/hMmTWbt3414t9ftdIuiIU7j80okq2YzAueo120M442xk1kDJWtmZTqWQn7wHDvMRipVOEOQ==",
+ "dependencies": {
+ "System.Collections.Immutable": "9.0.0"
+ }
+ },
+ "compositekey": {
+ "type": "Project"
+ }
+ },
+ "net9.0": {
+ "BenchmarkDotNet": {
+ "type": "Direct",
+ "requested": "[0.15.8, )",
+ "resolved": "0.15.8",
+ "contentHash": "paCfrWxSeHqn3rUZc0spYXVFnHCF0nzRhG0nOLnyTjZYs8spsimBaaNmb3vwqvALKIplbYq/TF393vYiYSnh/Q==",
+ "dependencies": {
+ "BenchmarkDotNet.Annotations": "0.15.8",
+ "CommandLineParser": "2.9.1",
+ "Gee.External.Capstone": "2.3.0",
+ "Iced": "1.21.0",
+ "Microsoft.CodeAnalysis.CSharp": "4.14.0",
+ "Microsoft.Diagnostics.Runtime": "3.1.512801",
+ "Microsoft.Diagnostics.Tracing.TraceEvent": "3.1.21",
+ "Microsoft.DotNet.PlatformAbstractions": "3.1.6",
+ "Perfolizer": "[0.6.1]",
+ "System.Management": "9.0.5"
+ }
+ },
+ "DotNet.ReproducibleBuilds": {
+ "type": "Direct",
+ "requested": "[1.2.39, )",
+ "resolved": "1.2.39",
+ "contentHash": "fcFN01tDTIQqDuTwr1jUQK/geofiwjG5DycJQOnC72i1SsLAk1ELe+apBOuZ11UMQG8YKFZG1FgvjZPbqHyatg=="
+ },
+ "BenchmarkDotNet.Annotations": {
+ "type": "Transitive",
+ "resolved": "0.15.8",
+ "contentHash": "hfucY0ycAsB0SsoaZcaAp9oq5wlWBJcylvEJb9pmvdYUx6PD6S4mDiYnZWjdjAlLhIpe/xtGCwzORfzAzPqvzA=="
+ },
+ "CommandLineParser": {
+ "type": "Transitive",
+ "resolved": "2.9.1",
+ "contentHash": "OE0sl1/sQ37bjVsPKKtwQlWDgqaxWgtme3xZz7JssWUzg5JpMIyHgCTY9MVMxOg48fJ1AgGT3tgdH5m/kQ5xhA=="
+ },
+ "Gee.External.Capstone": {
+ "type": "Transitive",
+ "resolved": "2.3.0",
+ "contentHash": "2ap/rYmjtzCOT8hxrnEW/QeiOt+paD8iRrIcdKX0cxVwWLFa1e+JDBNeECakmccXrSFeBQuu5AV8SNkipFMMMw=="
+ },
+ "Iced": {
+ "type": "Transitive",
+ "resolved": "1.21.0",
+ "contentHash": "dv5+81Q1TBQvVMSOOOmRcjJmvWcX3BZPZsIq31+RLc5cNft0IHAyNlkdb7ZarOWG913PyBoFDsDXoCIlKmLclg=="
+ },
+ "Microsoft.CodeAnalysis.Analyzers": {
+ "type": "Transitive",
+ "resolved": "3.11.0",
+ "contentHash": "v/EW3UE8/lbEYHoC2Qq7AR/DnmvpgdtAMndfQNmpuIMx/Mto8L5JnuCfdBYtgvalQOtfNCnxFejxuRrryvUTsg=="
+ },
+ "Microsoft.CodeAnalysis.Common": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "PC3tuwZYnC+idaPuoC/AZpEdwrtX7qFpmnrfQkgobGIWiYmGi5MCRtl5mx6QrfMGQpK78X2lfIEoZDLg/qnuHg==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0"
+ }
+ },
+ "Microsoft.CodeAnalysis.CSharp": {
+ "type": "Transitive",
+ "resolved": "4.14.0",
+ "contentHash": "568a6wcTivauIhbeWcCwfWwIn7UV7MeHEBvFB2uzGIpM2OhJ4eM/FZ8KS0yhPoNxnSpjGzz7x7CIjTxhslojQA==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.11.0",
+ "Microsoft.CodeAnalysis.Common": "[4.14.0]"
+ }
+ },
+ "Microsoft.Diagnostics.NETCore.Client": {
+ "type": "Transitive",
+ "resolved": "0.2.510501",
+ "contentHash": "juoqJYMDs+lRrrZyOkXXMImJHneCF23cuvO4waFRd2Ds7j+ZuGIPbJm0Y/zz34BdeaGiiwGWraMUlln05W1PCQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "6.0.0"
+ }
+ },
+ "Microsoft.Diagnostics.Runtime": {
+ "type": "Transitive",
+ "resolved": "3.1.512801",
+ "contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==",
+ "dependencies": {
+ "Microsoft.Diagnostics.NETCore.Client": "0.2.410101"
+ }
+ },
+ "Microsoft.Diagnostics.Tracing.TraceEvent": {
+ "type": "Transitive",
+ "resolved": "3.1.21",
+ "contentHash": "/OrJFKaojSR6TkUKtwh8/qA9XWNtxLrXMqvEb89dBSKCWjaGVTbKMYodIUgF5deCEtmd6GXuRerciXGl5bhZ7Q==",
+ "dependencies": {
+ "Microsoft.Diagnostics.NETCore.Client": "0.2.510501"
+ }
+ },
+ "Microsoft.DotNet.PlatformAbstractions": {
+ "type": "Transitive",
+ "resolved": "3.1.6",
+ "contentHash": "jek4XYaQ/PGUwDKKhwR8K47Uh1189PFzMeLqO83mXrXQVIpARZCcfuDedH50YDTepBkfijCZN5U/vZi++erxtg=="
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "6.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "6.0.0",
+ "Microsoft.Extensions.Options": "6.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA=="
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
+ "Microsoft.Extensions.Primitives": "6.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ=="
+ },
+ "Perfolizer": {
+ "type": "Transitive",
+ "resolved": "0.6.1",
+ "contentHash": "CR1QmWg4XYBd1Pb7WseP+sDmV8nGPwvmowKynExTqr3OuckIGVMhvmN4LC5PGzfXqDlR295+hz/T7syA1CxEqA==",
+ "dependencies": {
+ "Pragmastat": "3.2.4"
+ }
+ },
+ "Pragmastat": {
+ "type": "Transitive",
+ "resolved": "3.2.4",
+ "contentHash": "I5qFifWw/gaTQT52MhzjZpkm/JPlfjSeO/DTZJjO7+hTKI+0aGRgOgZ3NN6D96dDuuqbIAZSeA5RimtHjqrA2A=="
+ },
+ "System.CodeDom": {
+ "type": "Transitive",
+ "resolved": "9.0.5",
+ "contentHash": "cuzLM2MWutf9ZBEMPYYfd0DXwYdvntp7VCT6a/wvbKCa2ZuvGmW74xi+YBa2mrfEieAXqM4TNKlMmSnfAfpUoQ=="
+ },
+ "System.Management": {
+ "type": "Transitive",
+ "resolved": "9.0.5",
+ "contentHash": "n6o9PZm9p25+zAzC3/48K0oHnaPKTInRrxqFq1fi/5TPbMLjuoCm/h//mS3cUmSy+9AO1Z+qsC/Ilt/ZFatv5Q==",
+ "dependencies": {
+ "System.CodeDom": "9.0.5"
+ }
+ },
+ "compositekey": {
+ "type": "Project"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index d50530f..3eb45bd 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -17,6 +17,11 @@
+
+
+
+
+