From 658164813a3088c5401e0d4d1b0e6ca1dcd5164f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabr=C3=ADcio=20Godoy?= Date: Sun, 6 Oct 2024 11:53:00 -0300 Subject: [PATCH] feat: Optimize and fix issues (#206) - Create benchmarks to assess basic formatting and parsing, including flags enumerations. - Add benchmark reports for formatting and parsing enumeration values. - The JSON converter now supports flags enumerations. - Only generate metadata classes when an `EnumGeneratorAttribute` is present. - Removed the `Formatter` and `Parser` classes to improve inlining and performance. - Added support for generating metadata for JSON-serialized values. - Organized interlocked generator code. - Implemented the ability to generate the `ToJsonString` extension method and variants of `TryParseJsonString` factory methods. - Added support for case-insensitive reading of JSON values on generated JSON converters. BREAKING CHANGE: Removed parsing of comma-separated values for non-flag enumerations. --- EnumUtilities.sln | 9 + ...chmark.Tests.BigEnumParse-report-github.md | 37 + ...ark.Tests.BigEnumToString-report-github.md | 37 + ...k.Tests.BigFlagsEnumParse-report-github.md | 51 + ...ests.BigFlagsEnumToString-report-github.md | 43 + ...mark.Tests.SmallEnumParse-report-github.md | 37 + ...k.Tests.SmallEnumToString-report-github.md | 37 + ...Tests.SmallFlagsEnumParse-report-github.md | 41 + ...ts.SmallFlagsEnumToString-report-github.md | 37 + ...s.SpanAndStringComparison-report-github.md | 18 + ...mark.Tests.StringCreation-report-github.md | 18 + .../CodeWriters/EnumExtensionsWriter.cs | 1224 +++++- .../CodeWriters/EnumExtensionsWriter.tt | 26 +- .../CodeWriters/EnumFactoryWriter.cs | 3645 +++++++++++++---- .../CodeWriters/EnumFactoryWriter.tt | 55 +- .../EnumInfo/DefaultBlock.ttinclude | 90 +- .../EnumInfo/ExtensionsBlock.ttinclude | 336 -- .../EnumInfo/FactoryBlock.ttinclude | 208 - .../EnumInfo/NamesInternal.ttinclude | 45 + .../CodeWriters/EnumInfoWriter.cs | 2618 +----------- .../CodeWriters/EnumInfoWriter.tt | 34 +- .../CodeWriters/EnumJsonConverterWriter.cs | 196 +- .../CodeWriters/EnumJsonConverterWriter.tt | 139 +- .../Extensions/DefaultBlock.ttinclude | 22 +- .../Extensions/EnumMemberBlock.ttinclude | 8 +- .../Extensions/FormatStringInternal.ttinclude | 183 + .../Extensions/InterlockedBlock.ttinclude | 16 +- .../Extensions/JsonBlock.ttinclude | 23 + .../Factory/DefaultBlock.ttinclude | 115 +- .../Factory/DescriptionBlock.ttinclude | 43 +- .../Factory/EnumMemberBlock.ttinclude | 55 +- .../CodeWriters/Factory/JsonBlock.ttinclude | 152 + .../Factory/LegacyDefaultBlock.ttinclude | 88 - .../Factory/MiscellaneousBlock.ttinclude | 6 - .../Factory/TryParseInternal.ttinclude | 214 + .../Models/EnumToGenerate.cs | 84 +- .../Models/EnumValue.cs | 45 +- .../Models/JsonConverterGeneratorOptions.cs | 3 + perf/Directory.Build.props | 10 + .../Config/BenchmarkConfig.cs | 25 + .../Config/RuntimeContext.cs | 22 + .../EnumUtilities.Benchmark.csproj | 21 + perf/EnumUtilities.Benchmark/Models/Elf.cs | 42 + .../Models/Permissions.cs | 44 + .../Models/UserRole.cs | 17 + perf/EnumUtilities.Benchmark/Models/Valar.cs | 18 + perf/EnumUtilities.Benchmark/Program.cs | 7 + .../Tests/BigEnumParse.cs | 33 + .../Tests/BigEnumToString.cs | 33 + .../Tests/BigFlagsEnumParse.cs | 36 + .../Tests/BigFlagsEnumToString.cs | 33 + .../Tests/SmallEnumParse.cs | 33 + .../Tests/SmallEnumToString.cs | 33 + .../Tests/SmallFlagsEnumParse.cs | 33 + .../Tests/SmallFlagsEnumToString.cs | 33 + .../Tests/SpanAndStringComparison.cs | 22 + .../Tests/StringCreation.cs | 75 + .../packages.lock.json | 288 ++ .../Formatters/EnumStringFormatter.cs | 87 +- .../Formatters/IEnumFlagsFormatter.cs | 11 - .../Formatters/IEnumFormatter.cs | 30 - .../JsonConverterGeneratorAttribute.cs | 15 + src/EnumUtilities/Parsers/EnumStringParser.cs | 195 - .../Parsers/FlagsEnumTokenizer.cs | 2 +- .../Parsers/IEnumDescriptionParser.cs | 6 - src/EnumUtilities/Parsers/IEnumParser.cs | 28 - src/EnumUtilities/Parsers/ThrowHelper.cs | 59 + .../EnumFactoryTests.cs | 1 - ...tionTests.Models.BigErrorCodeEnumInfo.g.cs | 126 - ...onTests.Models.BigErrorCodeExtensions.g.cs | 54 + ...ationTests.Models.BigErrorCodeFactory.g.cs | 244 ++ ...ests.Models.BigErrorCodeJsonConverter.g.cs | 113 +- ...rationTests.Models.CategoriesEnumInfo.g.cs | 126 +- ...tionTests.Models.CategoriesExtensions.g.cs | 49 +- ...grationTests.Models.CategoriesFactory.g.cs | 170 +- ...tionTests.Models.CategoriesValidation.g.cs | 2 +- ...tegrationTests.Models.ColoursEnumInfo.g.cs | 171 +- ...grationTests.Models.ColoursExtensions.g.cs | 141 +- ...ntegrationTests.Models.ColoursFactory.g.cs | 170 +- ...grationTests.Models.ColoursValidation.g.cs | 2 +- ...grationTests.Models.ErrorCodeEnumInfo.g.cs | 126 - ...ationTests.Models.ErrorCodeExtensions.g.cs | 53 + ...egrationTests.Models.ErrorCodeFactory.g.cs | 244 ++ ...onTests.Models.ErrorCodeJsonConverter.g.cs | 113 +- ...ationTests.Models.HumanStatesEnumInfo.g.cs | 136 +- ...ionTests.Models.HumanStatesExtensions.g.cs | 48 +- ...rationTests.Models.HumanStatesFactory.g.cs | 182 +- ...ionTests.Models.HumanStatesValidation.g.cs | 2 +- ...tegrationTests.Models.MyEnum1EnumInfo.g.cs | 105 +- ...grationTests.Models.MyEnum1Extensions.g.cs | 40 +- ...ntegrationTests.Models.MyEnum1Factory.g.cs | 155 +- ...grationTests.Models.MyEnum1Validation.g.cs | 2 +- ...tegrationTests.Models.MyEnum2EnumInfo.g.cs | 236 +- ...grationTests.Models.MyEnum2Extensions.g.cs | 74 +- ...ntegrationTests.Models.MyEnum2Factory.g.cs | 364 +- ...grationTests.Models.MyEnum2Validation.g.cs | 2 +- ...tegrationTests.Models.MyEnum3EnumInfo.g.cs | 137 +- ...grationTests.Models.MyEnum3Extensions.g.cs | 52 +- ...ntegrationTests.Models.MyEnum3Factory.g.cs | 179 +- ...grationTests.Models.MyEnum3Validation.g.cs | 2 +- ...ionTests.Models.PaymentMethodEnumInfo.g.cs | 236 +- ...nTests.Models.PaymentMethodExtensions.g.cs | 74 +- ...tionTests.Models.PaymentMethodFactory.g.cs | 364 +- ...nTests.Models.PaymentMethodValidation.g.cs | 2 +- ...ntegrationTests.Models.SeasonEnumInfo.g.cs | 120 - ...egrationTests.Models.SeasonExtensions.g.cs | 56 + ...IntegrationTests.Models.SeasonFactory.g.cs | 235 ++ ...ationTests.Models.SeasonJsonConverter.g.cs | 109 +- ...onTests.Models.SlimCategoriesEnumInfo.g.cs | 126 +- ...Tests.Models.SlimCategoriesExtensions.g.cs | 49 +- ...ionTests.Models.SlimCategoriesFactory.g.cs | 170 +- ...Tests.Models.SlimCategoriesValidation.g.cs | 2 +- ...rationTests.Models.StatusCodeEnumInfo.g.cs | 404 +- ...tionTests.Models.StatusCodeExtensions.g.cs | 109 +- ...grationTests.Models.StatusCodeFactory.g.cs | 406 +- ...tionTests.Models.StatusCodeValidation.g.cs | 2 +- ...egrationTests.Models.UserRoleEnumInfo.g.cs | 460 +-- ...rationTests.Models.UserRoleExtensions.g.cs | 337 +- ...tegrationTests.Models.UserRoleFactory.g.cs | 358 +- ...rationTests.Models.UserRoleValidation.g.cs | 2 +- ...egrationTests.Models.WeekDaysEnumInfo.g.cs | 137 +- ...rationTests.Models.WeekDaysExtensions.g.cs | 52 +- ...tegrationTests.Models.WeekDaysFactory.g.cs | 179 +- ...rationTests.Models.WeekDaysValidation.g.cs | 2 +- .../_.NoNamespaceEnumInfo.g.cs | 105 +- .../_.NoNamespaceExtensions.g.cs | 40 +- .../_.NoNamespaceFactory.g.cs | 155 +- .../_.NoNamespaceValidation.g.cs | 2 +- version.json | 2 +- 129 files changed, 10968 insertions(+), 8277 deletions(-) create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigEnumParse-report-github.md create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigEnumToString-report-github.md create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigFlagsEnumParse-report-github.md create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigFlagsEnumToString-report-github.md create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallEnumParse-report-github.md create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallEnumToString-report-github.md create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallFlagsEnumParse-report-github.md create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallFlagsEnumToString-report-github.md create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SpanAndStringComparison-report-github.md create mode 100644 docs/benchmarks/results/EnumUtilities.Benchmark.Tests.StringCreation-report-github.md delete mode 100644 gen/EnumUtilities.Generators/CodeWriters/EnumInfo/ExtensionsBlock.ttinclude delete mode 100644 gen/EnumUtilities.Generators/CodeWriters/EnumInfo/FactoryBlock.ttinclude create mode 100644 gen/EnumUtilities.Generators/CodeWriters/EnumInfo/NamesInternal.ttinclude create mode 100644 gen/EnumUtilities.Generators/CodeWriters/Extensions/FormatStringInternal.ttinclude create mode 100644 gen/EnumUtilities.Generators/CodeWriters/Extensions/JsonBlock.ttinclude create mode 100644 gen/EnumUtilities.Generators/CodeWriters/Factory/JsonBlock.ttinclude delete mode 100644 gen/EnumUtilities.Generators/CodeWriters/Factory/LegacyDefaultBlock.ttinclude create mode 100644 gen/EnumUtilities.Generators/CodeWriters/Factory/TryParseInternal.ttinclude create mode 100644 perf/Directory.Build.props create mode 100644 perf/EnumUtilities.Benchmark/Config/BenchmarkConfig.cs create mode 100644 perf/EnumUtilities.Benchmark/Config/RuntimeContext.cs create mode 100644 perf/EnumUtilities.Benchmark/EnumUtilities.Benchmark.csproj create mode 100644 perf/EnumUtilities.Benchmark/Models/Elf.cs create mode 100644 perf/EnumUtilities.Benchmark/Models/Permissions.cs create mode 100644 perf/EnumUtilities.Benchmark/Models/UserRole.cs create mode 100644 perf/EnumUtilities.Benchmark/Models/Valar.cs create mode 100644 perf/EnumUtilities.Benchmark/Program.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/BigEnumParse.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/BigEnumToString.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/BigFlagsEnumParse.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/BigFlagsEnumToString.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/SmallEnumParse.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/SmallEnumToString.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/SmallFlagsEnumParse.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/SmallFlagsEnumToString.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/SpanAndStringComparison.cs create mode 100644 perf/EnumUtilities.Benchmark/Tests/StringCreation.cs create mode 100644 perf/EnumUtilities.Benchmark/packages.lock.json delete mode 100644 src/EnumUtilities/Formatters/IEnumFlagsFormatter.cs delete mode 100644 src/EnumUtilities/Formatters/IEnumFormatter.cs delete mode 100644 src/EnumUtilities/Parsers/EnumStringParser.cs delete mode 100644 src/EnumUtilities/Parsers/IEnumDescriptionParser.cs delete mode 100644 src/EnumUtilities/Parsers/IEnumParser.cs create mode 100644 src/EnumUtilities/Parsers/ThrowHelper.cs delete mode 100644 tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeEnumInfo.g.cs create mode 100644 tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeExtensions.g.cs create mode 100644 tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeFactory.g.cs delete mode 100644 tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeEnumInfo.g.cs create mode 100644 tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeExtensions.g.cs create mode 100644 tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeFactory.g.cs delete mode 100644 tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonEnumInfo.g.cs create mode 100644 tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonExtensions.g.cs create mode 100644 tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonFactory.g.cs diff --git a/EnumUtilities.sln b/EnumUtilities.sln index 5f4ca34..5afba56 100644 --- a/EnumUtilities.sln +++ b/EnumUtilities.sln @@ -18,6 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{45CCED50-B3C EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0BEA25FB-CD38-4C71-B002-F72F966A2824}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "perf", "perf", "{23E5FDE1-F962-4FBE-B97E-2275D246542F}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumUtilities.Generators", "gen\EnumUtilities.Generators\EnumUtilities.Generators.csproj", "{E59B1284-D38F-4397-93E5-0DA3356ACE63}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumUtilities", "src\EnumUtilities\EnumUtilities.csproj", "{02B0B1F0-42E6-43C3-B9C2-F06A089AD1F5}" @@ -28,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumUtilities.Generators.In EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumUtilities.Tests", "tests\EnumUtilities.Tests\EnumUtilities.Tests.csproj", "{8242CFFA-AA6F-46CC-8FC0-EC62BA21E91F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumUtilities.Benchmark", "perf\EnumUtilities.Benchmark\EnumUtilities.Benchmark.csproj", "{2F22069E-EB66-4394-AFA9-78B95F8C97EC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -42,6 +46,7 @@ Global {E59B1284-D38F-4397-93E5-0DA3356ACE63} = {B003C044-6A35-4ABD-9B4C-8FF0C46220CD} {AA4D1754-CB69-4333-8898-65FFFB38BEEE} = {0BEA25FB-CD38-4C71-B002-F72F966A2824} {8242CFFA-AA6F-46CC-8FC0-EC62BA21E91F} = {0BEA25FB-CD38-4C71-B002-F72F966A2824} + {2F22069E-EB66-4394-AFA9-78B95F8C97EC} = {23E5FDE1-F962-4FBE-B97E-2275D246542F} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {02B0B1F0-42E6-43C3-B9C2-F06A089AD1F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -64,5 +69,9 @@ Global {8242CFFA-AA6F-46CC-8FC0-EC62BA21E91F}.Debug|Any CPU.Build.0 = Debug|Any CPU {8242CFFA-AA6F-46CC-8FC0-EC62BA21E91F}.Release|Any CPU.ActiveCfg = Release|Any CPU {8242CFFA-AA6F-46CC-8FC0-EC62BA21E91F}.Release|Any CPU.Build.0 = Release|Any CPU + {2F22069E-EB66-4394-AFA9-78B95F8C97EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F22069E-EB66-4394-AFA9-78B95F8C97EC}.Release|Any CPU.Build.0 = Release|Any CPU + {2F22069E-EB66-4394-AFA9-78B95F8C97EC}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {2F22069E-EB66-4394-AFA9-78B95F8C97EC}.Debug|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigEnumParse-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigEnumParse-report-github.md new file mode 100644 index 0000000..3d659ec --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigEnumParse-report-github.md @@ -0,0 +1,37 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.401 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | Elf | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio | +|------------------ |---------- |-----------:|----------:|----------:|------:|--------:|----------:|------------:| +| **BuiltInParse** | **0** | **14.092 ns** | **0.0950 ns** | **0.1362 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | 0 | 10.113 ns | 0.1324 ns | 0.1982 ns | 0.72 | 0.02 | - | NA | +| EnumsNetParse | 0 | 13.221 ns | 1.0329 ns | 1.5140 ns | 0.94 | 0.11 | - | NA | +| NetEscapadesParse | 0 | 12.523 ns | 0.1352 ns | 0.2024 ns | 0.89 | 0.02 | - | NA | +| RaiqubParse | 0 | 8.948 ns | 0.0174 ns | 0.0250 ns | 0.64 | 0.01 | - | NA | +| | | | | | | | | | +| **BuiltInParse** | **1000** | **17.552 ns** | **0.0592 ns** | **0.0830 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | 1000 | 14.647 ns | 0.1684 ns | 0.2520 ns | 0.83 | 0.01 | - | NA | +| EnumsNetParse | 1000 | 15.446 ns | 0.2096 ns | 0.3006 ns | 0.88 | 0.02 | - | NA | +| NetEscapadesParse | 1000 | 17.396 ns | 0.2157 ns | 0.3229 ns | 0.99 | 0.02 | - | NA | +| RaiqubParse | 1000 | 11.993 ns | 0.1449 ns | 0.2124 ns | 0.68 | 0.01 | - | NA | +| | | | | | | | | | +| **BuiltInParse** | **Aredhel** | **155.198 ns** | **0.9888 ns** | **1.4494 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | Aredhel | 16.344 ns | 0.3097 ns | 0.4342 ns | 0.11 | 0.00 | - | NA | +| EnumsNetParse | Aredhel | 23.796 ns | 0.1843 ns | 0.2701 ns | 0.15 | 0.00 | - | NA | +| NetEscapadesParse | Aredhel | 4.154 ns | 0.0123 ns | 0.0168 ns | 0.03 | 0.00 | - | NA | +| RaiqubParse | Aredhel | 30.648 ns | 0.1663 ns | 0.2438 ns | 0.20 | 0.00 | - | NA | +| | | | | | | | | | +| **BuiltInParse** | **Galadriel** | **24.391 ns** | **0.1304 ns** | **0.1870 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | Galadriel | 17.397 ns | 0.0476 ns | 0.0667 ns | 0.71 | 0.01 | - | NA | +| EnumsNetParse | Galadriel | 27.588 ns | 1.8840 ns | 2.5788 ns | 1.13 | 0.10 | - | NA | +| NetEscapadesParse | Galadriel | 4.981 ns | 0.0165 ns | 0.0236 ns | 0.20 | 0.00 | - | NA | +| RaiqubParse | Galadriel | 15.842 ns | 0.0658 ns | 0.0943 ns | 0.65 | 0.01 | - | NA | diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigEnumToString-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigEnumToString-report-github.md new file mode 100644 index 0000000..277493c --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigEnumToString-report-github.md @@ -0,0 +1,37 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.402 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | Elf | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | +|--------------------- |---------- |-----------:|----------:|----------:|-----------:|------:|--------:|-------:|----------:|------------:| +| **BuiltInToString** | **0** | **22.5497 ns** | **0.5939 ns** | **0.8705 ns** | **22.2127 ns** | **1.00** | **0.05** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | 0 | 2.8814 ns | 0.0507 ns | 0.0711 ns | 2.8769 ns | 0.13 | 0.01 | - | - | 0.00 | +| EnumsNetAsString | 0 | 3.2005 ns | 0.0897 ns | 0.1343 ns | 3.1692 ns | 0.14 | 0.01 | - | - | 0.00 | +| NetEscapadesToString | 0 | 23.6147 ns | 0.6926 ns | 1.0366 ns | 23.3105 ns | 1.05 | 0.06 | 0.0057 | 24 B | 1.00 | +| RaiqubToString | 0 | 1.1136 ns | 0.0399 ns | 0.0585 ns | 1.1042 ns | 0.05 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **Galadriel** | **17.8062 ns** | **0.4506 ns** | **0.6744 ns** | **17.9230 ns** | **1.00** | **0.05** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | Galadriel | 1.1964 ns | 0.0613 ns | 0.0838 ns | 1.1702 ns | 0.07 | 0.01 | - | - | 0.00 | +| EnumsNetAsString | Galadriel | 1.3942 ns | 0.0218 ns | 0.0292 ns | 1.3933 ns | 0.08 | 0.00 | - | - | 0.00 | +| NetEscapadesToString | Galadriel | 0.5302 ns | 0.0167 ns | 0.0235 ns | 0.5234 ns | 0.03 | 0.00 | - | - | 0.00 | +| RaiqubToString | Galadriel | 1.0603 ns | 0.0301 ns | 0.0441 ns | 1.0709 ns | 0.06 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **Aredhel** | **19.4398 ns** | **0.5728 ns** | **0.8215 ns** | **19.1657 ns** | **1.00** | **0.06** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | Aredhel | 1.1834 ns | 0.0423 ns | 0.0606 ns | 1.1547 ns | 0.06 | 0.00 | - | - | 0.00 | +| EnumsNetAsString | Aredhel | 1.4383 ns | 0.0378 ns | 0.0554 ns | 1.4201 ns | 0.07 | 0.00 | - | - | 0.00 | +| NetEscapadesToString | Aredhel | 0.8025 ns | 0.1880 ns | 0.2696 ns | 0.6311 ns | 0.04 | 0.01 | - | - | 0.00 | +| RaiqubToString | Aredhel | 1.0795 ns | 0.0120 ns | 0.0160 ns | 1.0742 ns | 0.06 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **1000** | **30.5595 ns** | **0.7356 ns** | **1.0783 ns** | **30.5367 ns** | **1.00** | **0.05** | **0.0134** | **56 B** | **1.00** | +| FastEnumToString | 1000 | 10.5993 ns | 0.2819 ns | 0.4219 ns | 10.4117 ns | 0.35 | 0.02 | 0.0076 | 32 B | 0.57 | +| EnumsNetAsString | 1000 | 12.8773 ns | 0.2627 ns | 0.3683 ns | 12.7960 ns | 0.42 | 0.02 | 0.0076 | 32 B | 0.57 | +| NetEscapadesToString | 1000 | 31.9137 ns | 0.4518 ns | 0.6479 ns | 31.7924 ns | 1.05 | 0.04 | 0.0134 | 56 B | 1.00 | +| RaiqubToString | 1000 | 15.8590 ns | 0.3727 ns | 0.5578 ns | 15.7718 ns | 0.52 | 0.03 | 0.0076 | 32 B | 0.57 | diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigFlagsEnumParse-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigFlagsEnumParse-report-github.md new file mode 100644 index 0000000..10400cb --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigFlagsEnumParse-report-github.md @@ -0,0 +1,51 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.401 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | Permissions | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio | +|------------------ |--------------------- |-------------:|-----------:|-----------:|------:|--------:|----------:|------------:| +| **BuiltInParse** | **0** | **13.987 ns** | **0.0470 ns** | **0.0674 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | 0 | 9.442 ns | 0.0244 ns | 0.0325 ns | 0.68 | 0.00 | - | NA | +| EnumsNetParse | 0 | 47.279 ns | 1.1095 ns | 1.6607 ns | 3.38 | 0.12 | - | NA | +| NetEscapadesParse | 0 | 10.073 ns | 0.0595 ns | 0.0814 ns | 0.72 | 0.01 | - | NA | +| RaiqubParse | 0 | 10.300 ns | 0.0915 ns | 0.1341 ns | 0.74 | 0.01 | - | NA | +| | | | | | | | | | +| **BuiltInParse** | **Delet(...) Move [39]** | **309.194 ns** | **1.6450 ns** | **2.4112 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | Delet(...) Move [39] | NA | NA | NA | ? | ? | NA | ? | +| EnumsNetParse | Delet(...) Move [39] | 286.000 ns | 1.6095 ns | 2.3083 ns | 0.93 | 0.01 | - | NA | +| NetEscapadesParse | Delet(...) Move [39] | NA | NA | NA | ? | ? | NA | ? | +| RaiqubParse | Delet(...) Move [39] | 224.670 ns | 0.7306 ns | 1.0709 ns | 0.73 | 0.01 | - | NA | +| | | | | | | | | | +| **BuiltInParse** | **Read, Write** | **63.240 ns** | **0.3288 ns** | **0.4819 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | Read, Write | NA | NA | NA | ? | ? | NA | ? | +| EnumsNetParse | Read, Write | 95.609 ns | 0.7829 ns | 1.0975 ns | 1.51 | 0.02 | - | NA | +| NetEscapadesParse | Read, Write | NA | NA | NA | ? | ? | NA | ? | +| RaiqubParse | Read, Write | 55.005 ns | 0.2825 ns | 0.4052 ns | 0.87 | 0.01 | - | NA | +| | | | | | | | | | +| **BuiltInParse** | **Read(...)lock [245]** | **2,783.170 ns** | **17.6501 ns** | **23.5624 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | Read(...)lock [245] | NA | NA | NA | ? | ? | NA | ? | +| EnumsNetParse | Read(...)lock [245] | 1,659.957 ns | 19.1646 ns | 26.8661 ns | 0.60 | 0.01 | - | NA | +| NetEscapadesParse | Read(...)lock [245] | NA | NA | NA | ? | ? | NA | ? | +| RaiqubParse | Read(...)lock [245] | 1,539.143 ns | 5.4026 ns | 7.5737 ns | 0.55 | 0.01 | - | NA | +| | | | | | | | | | +| **BuiltInParse** | **Restore** | **79.891 ns** | **0.4963 ns** | **0.7428 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | Restore | 16.590 ns | 0.3468 ns | 0.5083 ns | 0.21 | 0.01 | - | NA | +| EnumsNetParse | Restore | 55.787 ns | 0.5216 ns | 0.7646 ns | 0.70 | 0.01 | - | NA | +| NetEscapadesParse | Restore | 3.887 ns | 0.0278 ns | 0.0399 ns | 0.05 | 0.00 | - | NA | +| RaiqubParse | Restore | 33.789 ns | 0.0832 ns | 0.1138 ns | 0.42 | 0.00 | - | NA | + +Benchmarks with issues: + BigFlagsEnumParse.FastEnumParse: MediumRun(IterationCount=15, LaunchCount=2, WarmupCount=10) [Permissions=Delet(...) Move [39]] + BigFlagsEnumParse.NetEscapadesParse: MediumRun(IterationCount=15, LaunchCount=2, WarmupCount=10) [Permissions=Delet(...) Move [39]] + BigFlagsEnumParse.FastEnumParse: MediumRun(IterationCount=15, LaunchCount=2, WarmupCount=10) [Permissions=Read, Write] + BigFlagsEnumParse.NetEscapadesParse: MediumRun(IterationCount=15, LaunchCount=2, WarmupCount=10) [Permissions=Read, Write] + BigFlagsEnumParse.FastEnumParse: MediumRun(IterationCount=15, LaunchCount=2, WarmupCount=10) [Permissions=Read(...)lock [245]] + BigFlagsEnumParse.NetEscapadesParse: MediumRun(IterationCount=15, LaunchCount=2, WarmupCount=10) [Permissions=Read(...)lock [245]] diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigFlagsEnumToString-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigFlagsEnumToString-report-github.md new file mode 100644 index 0000000..0804bac --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.BigFlagsEnumToString-report-github.md @@ -0,0 +1,43 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.402 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | Permissions | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | +|--------------------- |--------------------- |--------------:|-----------:|-----------:|--------------:|------:|--------:|-------:|----------:|------------:| +| **BuiltInToString** | **None** | **17.4106 ns** | **0.5216 ns** | **0.7807 ns** | **17.2003 ns** | **1.00** | **0.06** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | None | 1.7633 ns | 0.0314 ns | 0.0461 ns | 1.7427 ns | 0.10 | 0.00 | - | - | 0.00 | +| EnumsNetAsString | None | 10.7569 ns | 0.1239 ns | 0.1816 ns | 10.8469 ns | 0.62 | 0.03 | - | - | 0.00 | +| NetEscapadesToString | None | 0.8065 ns | 0.0080 ns | 0.0109 ns | 0.8033 ns | 0.05 | 0.00 | - | - | 0.00 | +| RaiqubToString | None | 4.9437 ns | 0.0668 ns | 0.0936 ns | 4.8902 ns | 0.28 | 0.01 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **Read, Write** | **54.7734 ns** | **0.5244 ns** | **0.7849 ns** | **54.8739 ns** | **1.00** | **0.02** | **0.0172** | **72 B** | **1.00** | +| FastEnumToString | Read, Write | 3.3109 ns | 0.0182 ns | 0.0249 ns | 3.3064 ns | 0.06 | 0.00 | - | - | 0.00 | +| EnumsNetAsString | Read, Write | 60.5186 ns | 0.6323 ns | 0.8864 ns | 60.3551 ns | 1.11 | 0.02 | 0.0362 | 152 B | 2.11 | +| NetEscapadesToString | Read, Write | 59.1108 ns | 0.9027 ns | 1.2655 ns | 59.0186 ns | 1.08 | 0.03 | 0.0172 | 72 B | 1.00 | +| RaiqubToString | Read, Write | 32.8484 ns | 0.4131 ns | 0.6055 ns | 32.6146 ns | 0.60 | 0.01 | 0.0114 | 48 B | 0.67 | +| | | | | | | | | | | | +| **BuiltInToString** | **Delet(...) Move [39]** | **79.4866 ns** | **0.9360 ns** | **1.3719 ns** | **79.3398 ns** | **1.00** | **0.02** | **0.0305** | **128 B** | **1.00** | +| FastEnumToString | Delet(...) Move [39] | 12.5736 ns | 0.2004 ns | 0.2676 ns | 12.5551 ns | 0.16 | 0.00 | 0.0076 | 32 B | 0.25 | +| EnumsNetAsString | Delet(...) Move [39] | 192.3880 ns | 1.7609 ns | 2.4104 ns | 192.2929 ns | 2.42 | 0.05 | 0.1070 | 448 B | 3.50 | +| NetEscapadesToString | Delet(...) Move [39] | 79.8912 ns | 2.4930 ns | 3.5754 ns | 80.3421 ns | 1.01 | 0.05 | 0.0305 | 128 B | 1.00 | +| RaiqubToString | Delet(...) Move [39] | 72.0406 ns | 3.3867 ns | 5.0690 ns | 73.7853 ns | 0.91 | 0.06 | 0.0248 | 104 B | 0.81 | +| | | | | | | | | | | | +| **BuiltInToString** | **Restore** | **31.8871 ns** | **0.2496 ns** | **0.3499 ns** | **31.9096 ns** | **1.00** | **0.02** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | Restore | 10.1447 ns | 0.0447 ns | 0.0641 ns | 10.1164 ns | 0.32 | 0.00 | - | - | 0.00 | +| EnumsNetAsString | Restore | 17.8343 ns | 0.1750 ns | 0.2396 ns | 17.8997 ns | 0.56 | 0.01 | - | - | 0.00 | +| NetEscapadesToString | Restore | 0.8086 ns | 0.0115 ns | 0.0165 ns | 0.8011 ns | 0.03 | 0.00 | - | - | 0.00 | +| RaiqubToString | Restore | 5.2155 ns | 0.0503 ns | 0.0688 ns | 5.1904 ns | 0.16 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **Read(...)lock [245]** | **294.0483 ns** | **19.8665 ns** | **29.7352 ns** | **298.3516 ns** | **1.01** | **0.14** | **0.1278** | **536 B** | **1.00** | +| FastEnumToString | Read(...)lock [245] | 16.9184 ns | 0.3611 ns | 0.5405 ns | 16.7432 ns | 0.06 | 0.01 | 0.0115 | 48 B | 0.09 | +| EnumsNetAsString | Read(...)lock [245] | 1,214.1650 ns | 16.6086 ns | 23.8195 ns | 1,214.4279 ns | 4.17 | 0.43 | 0.3300 | 1384 B | 2.58 | +| NetEscapadesToString | Read(...)lock [245] | 315.3307 ns | 17.9389 ns | 26.8501 ns | 321.4061 ns | 1.08 | 0.14 | 0.1278 | 536 B | 1.00 | +| RaiqubToString | Read(...)lock [245] | 394.1485 ns | 3.4109 ns | 5.1053 ns | 394.7210 ns | 1.35 | 0.14 | 0.1221 | 512 B | 0.96 | diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallEnumParse-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallEnumParse-report-github.md new file mode 100644 index 0000000..f990e46 --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallEnumParse-report-github.md @@ -0,0 +1,37 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.401 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | Valar | Mean | Error | StdDev | Median | Ratio | RatioSD | Allocated | Alloc Ratio | +|------------------ |------ |----------:|----------:|----------:|----------:|------:|--------:|----------:|------------:| +| **BuiltInParse** | **0** | **14.009 ns** | **0.0380 ns** | **0.0520 ns** | **13.988 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | 0 | 10.025 ns | 0.0689 ns | 0.1031 ns | 10.013 ns | 0.72 | 0.01 | - | NA | +| EnumsNetParse | 0 | 12.577 ns | 0.1104 ns | 0.1584 ns | 12.592 ns | 0.90 | 0.01 | - | NA | +| NetEscapadesParse | 0 | 9.304 ns | 0.1782 ns | 0.2667 ns | 9.256 ns | 0.66 | 0.02 | - | NA | +| RaiqubParse | 0 | 8.974 ns | 0.0363 ns | 0.0521 ns | 8.970 ns | 0.64 | 0.00 | - | NA | +| | | | | | | | | | | +| **BuiltInParse** | **1000** | **17.546 ns** | **0.0390 ns** | **0.0547 ns** | **17.546 ns** | **1.00** | **0.00** | **-** | **NA** | +| FastEnumParse | 1000 | 14.643 ns | 0.1779 ns | 0.2608 ns | 14.692 ns | 0.83 | 0.01 | - | NA | +| EnumsNetParse | 1000 | 15.048 ns | 0.1278 ns | 0.1792 ns | 14.988 ns | 0.86 | 0.01 | - | NA | +| NetEscapadesParse | 1000 | 12.921 ns | 0.3500 ns | 0.5130 ns | 12.877 ns | 0.74 | 0.03 | - | NA | +| RaiqubParse | 1000 | 11.739 ns | 0.0759 ns | 0.1039 ns | 11.698 ns | 0.67 | 0.01 | - | NA | +| | | | | | | | | | | +| **BuiltInParse** | **Manwe** | **25.912 ns** | **0.0853 ns** | **0.1196 ns** | **25.919 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | Manwe | 15.073 ns | 0.1319 ns | 0.1760 ns | 15.094 ns | 0.58 | 0.01 | - | NA | +| EnumsNetParse | Manwe | 22.680 ns | 0.3163 ns | 0.4536 ns | 22.935 ns | 0.88 | 0.02 | - | NA | +| NetEscapadesParse | Manwe | 4.153 ns | 0.0801 ns | 0.1199 ns | 4.152 ns | 0.16 | 0.00 | - | NA | +| RaiqubParse | Manwe | 15.512 ns | 0.0971 ns | 0.1361 ns | 15.470 ns | 0.60 | 0.01 | - | NA | +| | | | | | | | | | | +| **BuiltInParse** | **Orome** | **47.739 ns** | **0.3490 ns** | **0.5116 ns** | **47.641 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | Orome | 15.363 ns | 0.2900 ns | 0.3970 ns | 15.662 ns | 0.32 | 0.01 | - | NA | +| EnumsNetParse | Orome | 22.730 ns | 0.1685 ns | 0.2522 ns | 22.760 ns | 0.48 | 0.01 | - | NA | +| NetEscapadesParse | Orome | 4.248 ns | 0.0824 ns | 0.1233 ns | 4.249 ns | 0.09 | 0.00 | - | NA | +| RaiqubParse | Orome | 15.741 ns | 0.0944 ns | 0.1413 ns | 15.725 ns | 0.33 | 0.00 | - | NA | diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallEnumToString-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallEnumToString-report-github.md new file mode 100644 index 0000000..e492861 --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallEnumToString-report-github.md @@ -0,0 +1,37 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.402 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | Valar | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | +|--------------------- |------ |-----------:|----------:|----------:|-----------:|------:|--------:|-------:|----------:|------------:| +| **BuiltInToString** | **0** | **19.6044 ns** | **0.4683 ns** | **0.6716 ns** | **19.5574 ns** | **1.00** | **0.05** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | 0 | 2.8459 ns | 0.0652 ns | 0.0976 ns | 2.8312 ns | 0.15 | 0.01 | - | - | 0.00 | +| EnumsNetAsString | 0 | 3.1221 ns | 0.0549 ns | 0.0822 ns | 3.0909 ns | 0.16 | 0.01 | - | - | 0.00 | +| NetEscapadesToString | 0 | 20.2675 ns | 0.4122 ns | 0.6170 ns | 20.1215 ns | 1.03 | 0.05 | 0.0057 | 24 B | 1.00 | +| RaiqubToString | 0 | 1.1779 ns | 0.0283 ns | 0.0407 ns | 1.1641 ns | 0.06 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **Manwe** | **16.7010 ns** | **0.3702 ns** | **0.5309 ns** | **16.5678 ns** | **1.00** | **0.04** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | Manwe | 1.1979 ns | 0.0501 ns | 0.0750 ns | 1.1555 ns | 0.07 | 0.00 | - | - | 0.00 | +| EnumsNetAsString | Manwe | 1.4548 ns | 0.0330 ns | 0.0484 ns | 1.4489 ns | 0.09 | 0.00 | - | - | 0.00 | +| NetEscapadesToString | Manwe | 0.3467 ns | 0.0380 ns | 0.0569 ns | 0.3142 ns | 0.02 | 0.00 | - | - | 0.00 | +| RaiqubToString | Manwe | 1.1572 ns | 0.0072 ns | 0.0103 ns | 1.1564 ns | 0.07 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **Orome** | **16.7389 ns** | **0.3565 ns** | **0.5225 ns** | **16.7787 ns** | **1.00** | **0.04** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | Orome | 1.1582 ns | 0.0114 ns | 0.0157 ns | 1.1547 ns | 0.07 | 0.00 | - | - | 0.00 | +| EnumsNetAsString | Orome | 1.4048 ns | 0.0200 ns | 0.0273 ns | 1.3951 ns | 0.08 | 0.00 | - | - | 0.00 | +| NetEscapadesToString | Orome | 0.5997 ns | 0.0119 ns | 0.0163 ns | 0.5946 ns | 0.04 | 0.00 | - | - | 0.00 | +| RaiqubToString | Orome | 1.1680 ns | 0.0137 ns | 0.0196 ns | 1.1626 ns | 0.07 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **1000** | **28.9346 ns** | **0.9582 ns** | **1.4341 ns** | **28.3032 ns** | **1.00** | **0.07** | **0.0134** | **56 B** | **1.00** | +| FastEnumToString | 1000 | 10.7276 ns | 0.3232 ns | 0.4838 ns | 10.7191 ns | 0.37 | 0.02 | 0.0076 | 32 B | 0.57 | +| EnumsNetAsString | 1000 | 12.8546 ns | 0.2450 ns | 0.3514 ns | 12.7347 ns | 0.45 | 0.02 | 0.0076 | 32 B | 0.57 | +| NetEscapadesToString | 1000 | 29.8411 ns | 0.6350 ns | 0.8901 ns | 29.5377 ns | 1.03 | 0.06 | 0.0134 | 56 B | 1.00 | +| RaiqubToString | 1000 | 13.2219 ns | 0.3314 ns | 0.4858 ns | 13.0578 ns | 0.46 | 0.03 | 0.0076 | 32 B | 0.57 | diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallFlagsEnumParse-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallFlagsEnumParse-report-github.md new file mode 100644 index 0000000..1c01b7c --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallFlagsEnumParse-report-github.md @@ -0,0 +1,41 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.401 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | UserRole | Mean | Error | StdDev | Median | Ratio | RatioSD | Allocated | Alloc Ratio | +|------------------ |--------------------- |-----------:|----------:|----------:|-----------:|------:|--------:|----------:|------------:| +| **BuiltInParse** | **0** | **14.022 ns** | **0.0230 ns** | **0.0307 ns** | **14.017 ns** | **1.00** | **0.00** | **-** | **NA** | +| FastEnumParse | 0 | 10.012 ns | 0.1077 ns | 0.1612 ns | 10.057 ns | 0.71 | 0.01 | - | NA | +| EnumsNetParse | 0 | 50.657 ns | 2.8684 ns | 4.2044 ns | 47.094 ns | 3.61 | 0.29 | - | NA | +| NetEscapadesParse | 0 | 12.302 ns | 0.1605 ns | 0.2402 ns | 12.362 ns | 0.88 | 0.02 | - | NA | +| RaiqubParse | 0 | 9.005 ns | 0.0818 ns | 0.1173 ns | 8.968 ns | 0.64 | 0.01 | - | NA | +| | | | | | | | | | | +| **BuiltInParse** | **1000** | **17.456 ns** | **0.0863 ns** | **0.1238 ns** | **17.389 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | 1000 | 15.580 ns | 0.1854 ns | 0.2717 ns | 15.551 ns | 0.89 | 0.02 | - | NA | +| EnumsNetParse | 1000 | 54.989 ns | 2.8136 ns | 4.0352 ns | 51.950 ns | 3.15 | 0.23 | - | NA | +| NetEscapadesParse | 1000 | 13.685 ns | 0.1206 ns | 0.1730 ns | 13.650 ns | 0.78 | 0.01 | - | NA | +| RaiqubParse | 1000 | 11.706 ns | 0.0142 ns | 0.0190 ns | 11.701 ns | 0.67 | 0.00 | - | NA | +| | | | | | | | | | | +| **BuiltInParse** | **Finance** | **31.276 ns** | **0.0901 ns** | **0.1292 ns** | **31.251 ns** | **1.00** | **0.01** | **-** | **NA** | +| FastEnumParse | Finance | 17.342 ns | 0.3175 ns | 0.4554 ns | 17.383 ns | 0.55 | 0.01 | - | NA | +| EnumsNetParse | Finance | 56.770 ns | 1.1868 ns | 1.7397 ns | 57.285 ns | 1.82 | 0.06 | - | NA | +| NetEscapadesParse | Finance | 3.586 ns | 0.0131 ns | 0.0180 ns | 3.582 ns | 0.11 | 0.00 | - | NA | +| RaiqubParse | Finance | 23.580 ns | 0.0616 ns | 0.0922 ns | 23.575 ns | 0.75 | 0.00 | - | NA | +| | | | | | | | | | | +| **BuiltInParse** | **Norma(...)odian [21]** | **54.871 ns** | **0.5531 ns** | **0.8108 ns** | **55.448 ns** | **1.00** | **0.02** | **-** | **NA** | +| FastEnumParse | Norma(...)odian [21] | NA | NA | NA | NA | ? | ? | NA | ? | +| EnumsNetParse | Norma(...)odian [21] | 111.366 ns | 3.7530 ns | 5.3824 ns | 115.807 ns | 2.03 | 0.10 | - | NA | +| NetEscapadesParse | Norma(...)odian [21] | NA | NA | NA | NA | ? | ? | NA | ? | +| RaiqubParse | Norma(...)odian [21] | 51.310 ns | 1.1999 ns | 1.6821 ns | 52.648 ns | 0.94 | 0.03 | - | NA | + +Benchmarks with issues: + SmallFlagsEnumParse.FastEnumParse: MediumRun(IterationCount=15, LaunchCount=2, WarmupCount=10) [UserRole=Norma(...)odian [21]] + SmallFlagsEnumParse.NetEscapadesParse: MediumRun(IterationCount=15, LaunchCount=2, WarmupCount=10) [UserRole=Norma(...)odian [21]] diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallFlagsEnumToString-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallFlagsEnumToString-report-github.md new file mode 100644 index 0000000..8a27e76 --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SmallFlagsEnumToString-report-github.md @@ -0,0 +1,37 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.402 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | UserRole | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | +|--------------------- |--------------------- |-----------:|----------:|----------:|-----------:|------:|--------:|-------:|----------:|------------:| +| **BuiltInToString** | **None** | **19.1148 ns** | **0.4327 ns** | **0.6206 ns** | **19.2761 ns** | **1.00** | **0.05** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | None | 2.0306 ns | 0.0332 ns | 0.0487 ns | 2.0098 ns | 0.11 | 0.00 | - | - | 0.00 | +| EnumsNetAsString | None | 10.1247 ns | 0.0661 ns | 0.0969 ns | 10.1027 ns | 0.53 | 0.02 | - | - | 0.00 | +| NetEscapadesToString | None | 0.5979 ns | 0.0086 ns | 0.0124 ns | 0.5933 ns | 0.03 | 0.00 | - | - | 0.00 | +| RaiqubToString | None | 1.5882 ns | 1.0655 ns | 1.5618 ns | 3.0292 ns | 0.08 | 0.08 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **Norma(...)odian [21]** | **40.7145 ns** | **0.5689 ns** | **0.8515 ns** | **40.6010 ns** | **1.00** | **0.03** | **0.0210** | **88 B** | **1.00** | +| FastEnumToString | Norma(...)odian [21] | 4.1197 ns | 0.0378 ns | 0.0541 ns | 4.1236 ns | 0.10 | 0.00 | - | - | 0.00 | +| EnumsNetAsString | Norma(...)odian [21] | 88.4588 ns | 1.7050 ns | 2.4991 ns | 88.1528 ns | 2.17 | 0.07 | 0.0650 | 272 B | 3.09 | +| NetEscapadesToString | Norma(...)odian [21] | 40.2000 ns | 0.7233 ns | 1.0373 ns | 40.1987 ns | 0.99 | 0.03 | 0.0210 | 88 B | 1.00 | +| RaiqubToString | Norma(...)odian [21] | 26.8832 ns | 0.2570 ns | 0.3518 ns | 26.8011 ns | 0.66 | 0.02 | 0.0153 | 64 B | 0.73 | +| | | | | | | | | | | | +| **BuiltInToString** | **Finance** | **17.5430 ns** | **0.2216 ns** | **0.3317 ns** | **17.3545 ns** | **1.00** | **0.03** | **0.0057** | **24 B** | **1.00** | +| FastEnumToString | Finance | 2.0256 ns | 0.0409 ns | 0.0574 ns | 1.9936 ns | 0.12 | 0.00 | - | - | 0.00 | +| EnumsNetAsString | Finance | 10.6250 ns | 0.0748 ns | 0.1096 ns | 10.6391 ns | 0.61 | 0.01 | - | - | 0.00 | +| NetEscapadesToString | Finance | 0.6002 ns | 0.0071 ns | 0.0104 ns | 0.5971 ns | 0.03 | 0.00 | - | - | 0.00 | +| RaiqubToString | Finance | 3.0593 ns | 0.0289 ns | 0.0415 ns | 3.0409 ns | 0.17 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | +| **BuiltInToString** | **1000** | **31.7633 ns** | **0.5174 ns** | **0.7585 ns** | **31.5629 ns** | **1.00** | **0.03** | **0.0134** | **56 B** | **1.00** | +| FastEnumToString | 1000 | 12.9321 ns | 0.2368 ns | 0.3396 ns | 12.8832 ns | 0.41 | 0.01 | 0.0076 | 32 B | 0.57 | +| EnumsNetAsString | 1000 | 28.3015 ns | 0.5274 ns | 0.7393 ns | 28.5094 ns | 0.89 | 0.03 | 0.0076 | 32 B | 0.57 | +| NetEscapadesToString | 1000 | 36.0344 ns | 1.0062 ns | 1.4430 ns | 35.3920 ns | 1.14 | 0.05 | 0.0134 | 56 B | 1.00 | +| RaiqubToString | 1000 | 17.9861 ns | 0.1850 ns | 0.2711 ns | 17.9528 ns | 0.57 | 0.02 | 0.0076 | 32 B | 0.57 | diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SpanAndStringComparison-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SpanAndStringComparison-report-github.md new file mode 100644 index 0000000..2734016 --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.SpanAndStringComparison-report-github.md @@ -0,0 +1,18 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4169/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.401 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | Mean | Error | StdDev | Allocated | +|---------------------------- |---------:|----------:|----------:|----------:| +| WithSequenceEqual | 1.334 ns | 0.0204 ns | 0.0305 ns | - | +| WithIsExpression | 1.311 ns | 0.0057 ns | 0.0081 ns | - | +| WithEqualsOrdinal | 1.310 ns | 0.0047 ns | 0.0065 ns | - | +| WithEqualsOrdinalIgnoreCase | 1.327 ns | 0.0180 ns | 0.0264 ns | - | diff --git a/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.StringCreation-report-github.md b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.StringCreation-report-github.md new file mode 100644 index 0000000..498c4f3 --- /dev/null +++ b/docs/benchmarks/results/EnumUtilities.Benchmark.Tests.StringCreation-report-github.md @@ -0,0 +1,18 @@ +``` + +BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4037/23H2/2023Update/SunValley3) +AMD Ryzen 5 1600, 1 CPU, 12 logical and 6 physical cores +.NET SDK 8.0.401 + [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 + +Job=MediumRun Arguments=Default NuGetReferences=Default +IterationCount=15 LaunchCount=2 WarmupCount=10 + +``` +| Method | Mean | Error | StdDev | Gen0 | Allocated | +|----------------------- |----------:|---------:|---------:|-------:|----------:| +| UninitializedString | 15.88 ns | 0.102 ns | 0.153 ns | 0.0536 | 224 B | +| ZeroedString | 16.25 ns | 0.077 ns | 0.111 ns | 0.0536 | 224 B | +| MemoryMarshalReference | 381.08 ns | 2.460 ns | 3.448 ns | 0.9999 | 4184 B | +| UnsafePointer | 381.22 ns | 1.040 ns | 1.492 ns | 0.9999 | 4184 B | diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumExtensionsWriter.cs b/gen/EnumUtilities.Generators/CodeWriters/EnumExtensionsWriter.cs index 1d5ffaf..cb1d732 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumExtensionsWriter.cs +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumExtensionsWriter.cs @@ -34,8 +34,10 @@ public override string TransformText() this.Write("\r\n"); this.Write("\r\n"); this.Write("\r\n"); + this.Write("\r\n"); + this.Write("\r\n"); - #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" #nullable enable @@ -44,9 +46,9 @@ public override string TransformText() #line hidden this.Write("// \r\n#nullable enable\r\n\r\nusing System;\r\nusing System.Runtime.CompilerServices;\r\n"); - #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" - if (IsInterlockedSupported()) + if (Model.IsInterlockedSupported()) { @@ -54,7 +56,7 @@ public override string TransformText() #line hidden this.Write("using System.Threading;\r\n"); - #line 24 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" } @@ -63,7 +65,7 @@ public override string TransformText() #line hidden this.Write("using Raiqub.Generators.EnumUtilities.Formatters;\r\n\r\n#pragma warning disable CS1591 // publicly visible type or member must be documented\r\n\r\n"); - #line 31 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" if (!string.IsNullOrEmpty(Model.Namespace)) { @@ -77,107 +79,841 @@ public override string TransformText() #line hidden this.Write("[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]\r\n[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\""); - #line 40 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" this.Write(this.ToStringHelper.ToStringWithCulture(CurrentAssemblyName.Name)); #line default #line hidden this.Write("\", \""); - #line 40 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" this.Write(this.ToStringHelper.ToStringWithCulture(Append($"{CurrentAssemblyName.Version}"))); #line default #line hidden this.Write("\")]\r\n"); - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsPublic ? "public" : "internal")); #line default #line hidden this.Write(" static partial class "); - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); - - #line default - #line hidden - this.Write("Extensions\r\n{\r\n private static readonly "); - #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".StringFormatter s_stringFormatter = "); - - #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - this.Write(".StringFormatter.Instance;\r\n"); + this.Write("Extensions\r\n{\r\n"); - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 45 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" - if (Model.HasSerializationValue) + if ((Model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0) { + WriteDefaultBlock(); + WriteInterlockedBlock(); + WriteEnumMemberBlock(); + WriteDescriptionBlock(); + WriteDisplayBlock(); + } + WriteJsonBlock(); #line default #line hidden - this.Write(" private static readonly "); - - #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".SerializationStringFormatter s_serializationStringFormatter = "); - - #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".SerializationStringFormatter.Instance;\r\n"); + this.Write("}\r\n"); - #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 57 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + if (!string.IsNullOrEmpty(Model.Namespace)) + { + PopIndent(); + WriteLine("}"); } #line default #line hidden - this.Write("\r\n"); - - #line 53 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + return this.GenerationEnvironment.ToString(); + } + + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + private void WriteFormatString(Func keySelector, string type) + { + if (Model.IsFlags) + { + WriteFormatStringLookup(keySelector, type); + WriteLine(); + } + + WriteInlineFormatString(keySelector, type); + } + + private void WriteFormatStringLookup(Func keySelector, string type) + { + var valuesRanges = Model.GetEnumValueRangesByBitRange(); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" private static int? FormatFlag"); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("sLength("); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" value)\r\n {\r\n int? fastResult = Get"); + + + #line default + #line hidden + + #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("LengthInlined(value);\r\n if (fastResult is not null)\r\n {\r\n return fastResult.Value;\r\n }\r\n"); + + + #line default + #line hidden + + #line 24 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + if (Model.Values.All(x => keySelector(x) != "0")) + { + + + #line default + #line hidden + + #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("\r\n if (value == 0)\r\n {\r\n return 1;\r\n }\r\n"); + + + #line default + #line hidden + + #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } + + + #line default + #line hidden + + #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("\r\n int count = 0, foundItemsCount = 0;\r\n"); + + + #line default + #line hidden + + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + foreach (var (i, vRange) in valuesRanges.Index()) + { + if (vRange.Count == 0) + continue; + + + #line default + #line hidden + + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" if ("); + + + #line default + #line hidden + + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(EnumToGenerate.BitRangeConditionStrings[i])); + + + #line default + #line hidden + + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(")\r\n {\r\n"); + + + #line default + #line hidden + + #line 46 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + foreach (var curr in vRange) + { + + + #line default + #line hidden + + #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" if ((value & "); + + + #line default + #line hidden + + #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(") == "); + + + #line default + #line hidden + + #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(")\r\n {\r\n value -= "); + + + #line default + #line hidden + + #line 52 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 52 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(";\r\n count = checked(count + "); + + + #line default + #line hidden + + #line 53 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(keySelector(curr)!.Length)); + + + #line default + #line hidden + + #line 53 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(");\r\n foundItemsCount++;\r\n if (value == 0) goto CountLength;\r\n }\r\n"); + + + #line default + #line hidden + + #line 57 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } + + + #line default + #line hidden + + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" }\r\n"); + + + #line default + #line hidden + + #line 61 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } + + + #line default + #line hidden + + #line 65 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("\r\n if (value != 0)\r\n {\r\n return null;\r\n }\r\n\r\nCountLength:\r\n const int separatorStringLength = 2;\r\n return checked(count + (separatorStringLength * (foundItemsCount - 1)));\r\n }\r\n\r\n private static readonly string[] s_format"); + + + #line default + #line hidden + + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("s = new string["); + + + #line default + #line hidden + + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.InvertedValues.Count)); + + + #line default + #line hidden + + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("] { "); + + + #line default + #line hidden + + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + foreach (var (index, curr) in Model.InvertedValues.Index()) + { + if (index > 0) + Write(", "); + Write($"\"{keySelector(curr)}\""); + } + + + #line default + #line hidden + + #line 82 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" };\r\n\r\n private static string? FormatFlag"); + + + #line default + #line hidden + + #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("s("); + + + #line default + #line hidden + + #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" value)\r\n {\r\n string? result = Get"); + + + #line default + #line hidden + + #line 86 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 86 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("Inlined(value);\r\n if (result is null)\r\n {\r\n Span foundItems = stackalloc int["); + + + #line default + #line hidden + + #line 89 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.GetMappedBitCount())); + + + #line default + #line hidden + + #line 89 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("];\r\n if (TryFindFlags"); + + + #line default + #line hidden + + #line 90 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 90 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("s(value, foundItems, out int foundItemsCount, out int resultLength))\r\n {\r\n result = EnumStringFormatter.WriteMultipleFoundFlagsNames(s_format"); + + + #line default + #line hidden + + #line 92 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 92 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("s, foundItems, foundItemsCount, resultLength);\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private static bool TryFindFlags"); + + + #line default + #line hidden + + #line 99 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 99 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("s("); + + + #line default + #line hidden + + #line 99 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 99 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" value, Span foundItems, out int foundItemsCount, out int resultLength)\r\n {\r\n resultLength = 0;\r\n foundItemsCount = 0;\r\n"); + + + #line default + #line hidden + + #line 103 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + foreach (var (i, vRange) in valuesRanges.Index()) + { + if (vRange.Count == 0) + continue; + + + #line default + #line hidden + + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" if ("); + + + #line default + #line hidden + + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(EnumToGenerate.BitRangeConditionStrings[i])); + + + #line default + #line hidden + + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(")\r\n {\r\n"); + + + #line default + #line hidden + + #line 111 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + foreach (var curr in vRange) + { + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" if ((value & "); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(") == "); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(")\r\n {\r\n value -= "); + + + #line default + #line hidden + + #line 117 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 117 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(";\r\n resultLength = checked(resultLength + "); + + + #line default + #line hidden + + #line 118 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(keySelector(curr)!.Length)); + + + #line default + #line hidden + + #line 118 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(");\r\n foundItems[foundItemsCount++] = "); + + + #line default + #line hidden + + #line 119 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.InvertedValues.IndexOf(curr))); + + + #line default + #line hidden + + #line 119 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(";\r\n if (value == 0) return true;\r\n }\r\n"); + + + #line default + #line hidden + + #line 122 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } + + + #line default + #line hidden + + #line 125 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" }\r\n"); + + + #line default + #line hidden + + #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } + + + #line default + #line hidden + + #line 130 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("\r\n return value == 0;\r\n }\r\n"); + + + #line default + #line hidden + + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } + + private void WriteInlineFormatString(Func keySelector, string type) + { + + + #line default + #line hidden + + #line 138 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" private static int? Get"); + + + #line default + #line hidden + + #line 138 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 138 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("LengthInlined("); + + + #line default + #line hidden + + #line 138 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 138 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" value)\r\n {\r\n return value switch\r\n {\r\n"); + + + #line default + #line hidden + + #line 142 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + if (!Model.HasZeroMember) + { + + + #line default + #line hidden + + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" 0 => 1,\r\n"); + + + #line default + #line hidden + + #line 147 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } + foreach (var curr in Model.UniqueValues) + { + + + #line default + #line hidden + + #line 152 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" "); + + + #line default + #line hidden + + #line 152 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 152 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" => "); + + + #line default + #line hidden + + #line 152 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(keySelector(curr)!.Length)); + + + #line default + #line hidden + + #line 152 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(",\r\n"); + + + #line default + #line hidden + + #line 153 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } + + + #line default + #line hidden + + #line 156 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" _ => null\r\n };\r\n }\r\n\r\n private static string? Get"); + + + #line default + #line hidden + + #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); + + + #line default + #line hidden + + #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("Inlined("); + + + #line default + #line hidden + + #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" value)\r\n {\r\n return value switch\r\n {\r\n"); + + + #line default + #line hidden + + #line 164 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + if (!Model.HasZeroMember) + { + + + #line default + #line hidden + + #line 168 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" 0 => \"0\",\r\n"); + + + #line default + #line hidden + + #line 169 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } + foreach (var curr in Model.UniqueValues) + { + + + #line default + #line hidden + + #line 174 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" "); + + + #line default + #line hidden + + #line 174 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 174 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" => \""); + + + #line default + #line hidden + + #line 174 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(keySelector(curr))); + + + #line default + #line hidden + + #line 174 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write("\",\r\n"); + + + #line default + #line hidden + + #line 175 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" + + } - WriteDefaultBlock(); - WriteInterlockedBlock(); - WriteEnumMemberBlock(); - WriteDescriptionBlock(); - WriteDisplayBlock(); + + #line default + #line hidden + + #line 178 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" +this.Write(" _ => null\r\n };\r\n }\r\n"); - - #line default - #line hidden - this.Write("}\r\n"); - - #line 61 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + + #line default + #line hidden + + #line 181 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\FormatStringInternal.ttinclude" - if (!string.IsNullOrEmpty(Model.Namespace)) - { - PopIndent(); - WriteLine("}"); - } + } - - #line default - #line hidden - return this.GenerationEnvironment.ToString(); - } + + #line default + #line hidden #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" @@ -203,7 +939,21 @@ private void WriteDefaultBlock() #line hidden #line 7 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" -this.Write(" value)\r\n {\r\n return EnumStringFormatter.GetString(("); +this.Write(" value)\r\n {\r\n return "); + + + #line default + #line hidden + + #line 9 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsFlags ? "FormatFlagNames" : "GetNameInlined")); + + + #line default + #line hidden + + #line 9 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write("(("); #line default @@ -217,13 +967,27 @@ private void WriteDefaultBlock() #line hidden #line 9 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" -this.Write(")value, s_stringFormatter);\r\n }\r\n"); +this.Write(")value)\r\n ?? (("); + + + #line default + #line hidden + + #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(")value).ToString();\r\n }\r\n"); #line default #line hidden - #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 12 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" if (Model.IsFlags) { @@ -232,42 +996,42 @@ private void WriteDefaultBlock() #line default #line hidden - #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" -this.Write("\r\n /// Determines whether one or more bit fields are set in the current instance.\r\n /// An enumeration value.\r\n /// if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, .\r\n public static bool HasFlagFast(this "); + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write("\r\n /// Determines whether one or more bit fields are set in the current instance.\r\n /// An enumeration value.\r\n /// if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, .\r\n [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n public static bool HasFlagFast(this "); #line default #line hidden - #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" this.Write(" value, "); #line default #line hidden - #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" this.Write(" flag)\r\n {\r\n return (value & flag) == flag;\r\n }\r\n"); #line default #line hidden - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 25 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" } @@ -275,71 +1039,145 @@ private void WriteDefaultBlock() #line default #line hidden - #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" this.Write("\r\n /// Calculates the number of characters produced by converting the specified value to string.\r\n /// The value to calculate the number of characters.\r\n /// The number of characters produced by converting the specified value to string.\r\n public static int GetStringLength(this "); #line default #line hidden - #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" -this.Write(" value)\r\n {\r\n return EnumStringFormatter.GetStringLength(("); + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(" value)\r\n {\r\n return "); #line default #line hidden - #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsFlags ? "FormatFlagNamesLength" : "GetNameLengthInlined")); + + + #line default + #line hidden + + #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write("(("); + + + #line default + #line hidden + + #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" -this.Write(")value, s_stringFormatter);\r\n }\r\n\r\n /// Returns a boolean telling whether the value of this instance exists in the enumeration.\r\n /// true if the value of this instance exists in the enumeration; false otherwise.\r\n public static bool IsDefined(this "); + #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(")value)\r\n ?? EnumNumericFormatter.GetStringLength(("); + + + #line default + #line hidden + + #line 35 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 35 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(")value);\r\n }\r\n\r\n /// Returns a boolean telling whether the value of this instance exists in the enumeration.\r\n /// true if the value of this instance exists in the enumeration; false otherwise.\r\n public static bool IsDefined(this "); #line default #line hidden - #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 40 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" -this.Write(" value)\r\n {\r\n return "); + #line 40 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(" value)\r\n {\r\n return ("); + + + #line default + #line hidden + + #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(")value switch\r\n {\r\n"); + + + #line default + #line hidden + + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + + foreach (var curr in Model.UniqueValues) + { + + + #line default + #line hidden + + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(" "); + + + #line default + #line hidden + + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(" => true,\r\n"); #line default #line hidden - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + + } #line default #line hidden - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" -this.Write("Validation.IsDefined(value);\r\n }\r\n"); + #line 52 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" +this.Write(" _ => false\r\n };\r\n }\r\n\r\n"); #line default #line hidden - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + #line 56 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\DefaultBlock.ttinclude" + WriteFormatString(x => x.MemberName, "Name"); } @@ -350,7 +1188,7 @@ private void WriteDefaultBlock() private void WriteInterlockedBlock() { - string? underlyingType = GetInterlockedUnderlyingType(); + string? underlyingType = Model.InterlockedUnderlyingType; if (underlyingType is null) return; @@ -1542,20 +2380,6 @@ private void WriteInterlockedBlock() } } - private string? GetInterlockedUnderlyingType() - { - return Model.UnderlyingType switch - { - "int" => "int", - "long" => "long", - "uint" => "int", - "ulong" => "long", - _ => null - }; - } - - private bool IsInterlockedSupported() => GetInterlockedUnderlyingType() != null; - #line default #line hidden @@ -1586,7 +2410,21 @@ private void WriteEnumMemberBlock() #line hidden #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" -this.Write(" value)\r\n {\r\n return EnumStringFormatter.GetString(("); +this.Write(" value)\r\n {\r\n return "); + + + #line default + #line hidden + + #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsFlags ? "FormatFlagEnumMemberValues" : "GetEnumMemberValueInlined")); + + + #line default + #line hidden + + #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write("(("); #line default @@ -1600,42 +2438,85 @@ private void WriteEnumMemberBlock() #line hidden #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" -this.Write(")value, s_serializationStringFormatter);\r\n }\r\n\r\n public static int GetEnumMemberValueStringLength(this "); +this.Write(")value)\r\n ?? (("); + + + #line default + #line hidden + + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write(")value).ToString();\r\n }\r\n\r\n public static int GetEnumMemberValueStringLength(this "); #line default #line hidden - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" + #line 14 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" -this.Write(" value)\r\n {\r\n return EnumStringFormatter.GetStringLength(("); + #line 14 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write(" value)\r\n {\r\n return "); + + + #line default + #line hidden + + #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsFlags ? "FormatFlagEnumMemberValuesLength" : "GetEnumMemberValueLengthInlined")); + + + #line default + #line hidden + + #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write("(("); #line default #line hidden - #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" + #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" -this.Write(")value, s_serializationStringFormatter);\r\n }\r\n"); + #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write(")value)\r\n ?? EnumNumericFormatter.GetStringLength(("); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" +this.Write(")value);\r\n }\r\n\r\n"); + + + #line default + #line hidden + + #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\EnumMemberBlock.ttinclude" + WriteFormatString(x => x.ResolvedSerializedValue, "EnumMemberValue"); } @@ -2075,7 +2956,118 @@ private void WriteDisplayBlock() #line default #line hidden - #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" + + private void WriteJsonBlock() + { + if (!Model.HasJsonProperty && (Model.SelectedGenerators & SelectedGenerators.JsonConverter) == 0) + return; + + + #line default + #line hidden + + #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write("\r\n [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n public static string? ToJsonString(this "); + + + #line default + #line hidden + + #line 9 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 9 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(" value)\r\n {\r\n return "); + + + #line default + #line hidden + + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsFlags ? "FormatFlagJsonStrings" : "GetJsonStringInlined")); + + + #line default + #line hidden + + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write("(("); + + + #line default + #line hidden + + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(")value);\r\n }\r\n\r\n [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n public static int? GetJsonStringLength(this "); + + + #line default + #line hidden + + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(" value)\r\n {\r\n return "); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsFlags ? "FormatFlagJsonStringsLength" : "GetJsonStringLengthInlined")); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write("(("); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" +this.Write(")value);\r\n }\r\n\r\n"); + + + #line default + #line hidden + + #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Extensions\JsonBlock.ttinclude" + + WriteFormatString(x => x.ResolvedJsonValue, "JsonString"); + } + + + #line default + #line hidden + + #line 64 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumExtensionsWriter.tt" public EnumExtensionsWriter(StringBuilder builder) : base(builder) { @@ -2084,7 +3076,7 @@ public EnumExtensionsWriter(StringBuilder builder) : base(builder) public override string GetFileName() => $"{Model.Namespace ?? "_"}.{Model.Name}Extensions.g.cs"; protected override bool CanGenerateFor(EnumToGenerate model) => - (model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0; + (model.SelectedGenerators & (SelectedGenerators.MainGenerator | SelectedGenerators.JsonConverter)) != 0; #line default diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumExtensionsWriter.tt b/gen/EnumUtilities.Generators/CodeWriters/EnumExtensionsWriter.tt index 74642d3..9837cc2 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumExtensionsWriter.tt +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumExtensionsWriter.tt @@ -3,11 +3,13 @@ <#@ import namespace="Models" #> <#@ import namespace="System.Text" #> <#@ import namespace="T4CodeWriter" #> +<#@ include file="$(ProjectDir)CodeWriters\Extensions\FormatStringInternal.ttinclude" #> <#@ include file="$(ProjectDir)CodeWriters\Extensions\DefaultBlock.ttinclude" #> <#@ include file="$(ProjectDir)CodeWriters\Extensions\InterlockedBlock.ttinclude" #> <#@ include file="$(ProjectDir)CodeWriters\Extensions\EnumMemberBlock.ttinclude" #> <#@ include file="$(ProjectDir)CodeWriters\Extensions\DescriptionBlock.ttinclude" #> <#@ include file="$(ProjectDir)CodeWriters\Extensions\DisplayBlock.ttinclude" #> +<#@ include file="$(ProjectDir)CodeWriters\Extensions\JsonBlock.ttinclude" #> <# #nullable enable #> @@ -17,7 +19,7 @@ using System; using System.Runtime.CompilerServices; <# - if (IsInterlockedSupported()) + if (Model.IsInterlockedSupported()) { #> using System.Threading; @@ -40,22 +42,16 @@ using Raiqub.Generators.EnumUtilities.Formatters; [global::System.CodeDom.Compiler.GeneratedCodeAttribute("<#= CurrentAssemblyName.Name #>", "<#= Append($"{CurrentAssemblyName.Version}") #>")] <#= Model.IsPublic ? "public" : "internal" #> static partial class <#= Model.Name #>Extensions { - private static readonly <#= Model.MetadataClassName #>.StringFormatter s_stringFormatter = <#= Model.MetadataClassName #>.StringFormatter.Instance; <# - if (Model.HasSerializationValue) + if ((Model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0) { -#> - private static readonly <#= Model.MetadataClassName #>.SerializationStringFormatter s_serializationStringFormatter = <#= Model.MetadataClassName #>.SerializationStringFormatter.Instance; -<# + WriteDefaultBlock(); + WriteInterlockedBlock(); + WriteEnumMemberBlock(); + WriteDescriptionBlock(); + WriteDisplayBlock(); } -#> - -<# - WriteDefaultBlock(); - WriteInterlockedBlock(); - WriteEnumMemberBlock(); - WriteDescriptionBlock(); - WriteDisplayBlock(); + WriteJsonBlock(); #> } <# @@ -73,5 +69,5 @@ using Raiqub.Generators.EnumUtilities.Formatters; public override string GetFileName() => $"{Model.Namespace ?? "_"}.{Model.Name}Extensions.g.cs"; protected override bool CanGenerateFor(EnumToGenerate model) => - (model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0; + (model.SelectedGenerators & (SelectedGenerators.MainGenerator | SelectedGenerators.JsonConverter)) != 0; #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumFactoryWriter.cs b/gen/EnumUtilities.Generators/CodeWriters/EnumFactoryWriter.cs index 7140454..8013ed1 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumFactoryWriter.cs +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumFactoryWriter.cs @@ -34,118 +34,84 @@ public override string TransformText() this.Write("\r\n"); this.Write("\r\n"); this.Write("\r\n"); - this.Write("\r\n// \r\n#nullable enable\r\n\r\nusing System;\r\nusing System.Diagnostics.CodeAnalysis;\r\nusing System.Globalization;\r\nusing System.Runtime.CompilerServices;\r\nusing Raiqub.Generators.EnumUtilities.Parsers;\r\n\r\n#pragma warning disable CS1591 // publicly visible type or member must be documented\r\n\r\n"); + this.Write("\r\n"); + this.Write("\r\n"); - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" + #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" - if (!string.IsNullOrEmpty(Model.Namespace)) - { - WriteLine($"namespace {Model.Namespace}"); - WriteLine("{"); - PushIndent(); - } +#nullable enable + + + #line default + #line hidden + this.Write("// \r\n#nullable enable\r\n\r\nusing System;\r\nusing System.Diagnostics.CodeAnalysis;\r\nusing System.Globalization;\r\nusing System.Runtime.CompilerServices;\r\nusing Raiqub.Generators.EnumUtilities.Parsers;\r\n\r\n#pragma warning disable CS1591 // publicly visible type or member must be documented\r\n\r\n"); + + #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" + + if (!string.IsNullOrEmpty(Model.Namespace)) + { + WriteLine($"namespace {Model.Namespace}"); + WriteLine("{"); + PushIndent(); + } #line default #line hidden this.Write("[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]\r\n[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\""); - #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" + #line 36 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" this.Write(this.ToStringHelper.ToStringWithCulture(CurrentAssemblyName.Name)); #line default #line hidden this.Write("\", \""); - #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" + #line 36 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" this.Write(this.ToStringHelper.ToStringWithCulture(Append($"{CurrentAssemblyName.Version}"))); #line default #line hidden this.Write("\")]\r\n"); - #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" + #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsPublic ? "public" : "internal")); #line default #line hidden this.Write(" static partial class "); - #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" + #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - this.Write("Factory\r\n{\r\n private static readonly "); - - #line 35 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".StringParser s_stringParser = "); - - #line 35 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".StringParser.Instance;\r\n"); - - #line 36 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" - - if (Model.HasSerializationValue) - { - - - #line default - #line hidden - this.Write(" private static readonly "); - - #line 40 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".SerializationStringParser s_serializationStringParser = "); - - #line 40 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".SerializationStringParser.Instance;\r\n"); - - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" - - } - - - #line default - #line hidden - this.Write("\r\n"); + this.Write("Factory\r\n{\r\n"); - #line 45 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" + #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" - WriteDefaultBlock(); - WriteLegacyDefaultBlock(); - WriteEnumMemberBlock(); - WriteDescriptionBlock(); - WriteDisplayBlock(); - WriteMiscellaneousBlock(); + if ((Model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0) + { + WriteDefaultBlock(); + WriteEnumMemberBlock(); + WriteDescriptionBlock(); + WriteDisplayBlock(); + WriteMiscellaneousBlock(); + } + WriteJsonBlock(); #line default #line hidden this.Write("}\r\n"); - #line 54 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" + #line 51 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" - if (!string.IsNullOrEmpty(Model.Namespace)) - { - PopIndent(); - WriteLine("}"); - } + if (!string.IsNullOrEmpty(Model.Namespace)) + { + PopIndent(); + WriteLine("}"); + } #line default @@ -153,2216 +119,4475 @@ public override string TransformText() return this.GenerationEnvironment.ToString(); } - #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" - private void WriteDefaultBlock() + private static string GetIgnoreCaseToComparisonExpression() + => "ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal"; + + private static string GetComparisonExpression(bool ignoreCase) + => ignoreCase ? "StringComparison.OrdinalIgnoreCase" : "StringComparison.Ordinal"; + + private void WriteTryParse( + Func keySelector, + string type, + string parameterName = "value", + bool allowNumbers = true) { #line default #line hidden - #line 5 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified name or numeric value. Note that this value need not be a member of the "); + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" private static bool TryParse"); #line default #line hidden - #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); #line default #line hidden - #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" enumeration.\r\n /// is .\r\n /// is empty or does not represent a valid value.\r\n public static "); + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("(ReadOnlySpan "); #line default #line hidden - #line 14 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 14 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" Parse(string value, bool ignoreCase = false)\r\n {\r\n if (value is null) ThrowArgumentNullException(nameof(value));\r\n TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result);\r\n return result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified name or numeric value. Note that this value need not be a member of the "); + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(", StringComparison comparisonType, bool throwOnFailure, out "); #line default #line hidden - #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n public static "); + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" result)\r\n {\r\n if (!"); #line default #line hidden - #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" Parse(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n TryParse(value, ignoreCase, throwOnFailure: true, out var result);\r\n return result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified name or numeric value or null. Note that this value need not be a member of the "); + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(".IsEmpty)\r\n {\r\n"); #line default #line hidden - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + if (allowNumbers) + { #line default #line hidden - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n [return: NotNullIfNotNull(\"value\")]\r\n public static "); + #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" char c = "); #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write("? ParseOrNull(string? value, bool ignoreCase = false)\r\n {\r\n if (value is null) return null;\r\n TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result);\r\n return result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("[0];\r\n if (char.IsWhiteSpace(c))\r\n {\r\n "); #line default #line hidden - #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); + #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" = "); #line default #line hidden - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(".TrimStart();\r\n if ("); #line default #line hidden - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out "); + #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(".IsEmpty)\r\n {\r\n goto ParseFailure;\r\n }\r\n\r\n c = "); #line default #line hidden - #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("[0];\r\n }\r\n\r\n if ((c < '0' || c > '9') && c != '-' && c != '+')\r\n {\r\n return TryParseNonNumeric"); #line default #line hidden - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); #line default #line hidden - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); + #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("("); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(", comparisonType, throwOnFailure, out result);\r\n }\r\n\r\n bool success = EnumNumericParser.TryParse("); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 40 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParse([NotNullWhen(true)] string? value, out "); + #line 40 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(", out result);\r\n if (success)\r\n {\r\n return true;\r\n }\r\n\r\n"); #line default #line hidden - #line 79 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 46 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } #line default #line hidden - #line 79 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" return TryParseNonNumeric"); #line default #line hidden - #line 91 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); #line default #line hidden - #line 91 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains null value.\r\n /// \r\n public static "); + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("("); #line default #line hidden - #line 94 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 94 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write("? TryParse(string? value, bool ignoreCase = false)\r\n {\r\n return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out "); + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(", comparisonType, throwOnFailure, out result);\r\n }\r\n\r\n"); #line default #line hidden - #line 96 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 52 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + if (allowNumbers) + { #line default #line hidden - #line 96 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 56 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" ParseFailure:\r\n"); #line default #line hidden - #line 106 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 57 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } #line default #line hidden - #line 106 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" if (throwOnFailure)\r\n {\r\n ThrowHelper.ThrowInvalidEmptyParseArgument(nameof("); #line default #line hidden - #line 108 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 62 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 108 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 62 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("));\r\n }\r\n\r\n result = 0;\r\n return false;\r\n }\r\n"); #line default #line hidden - #line 108 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + WriteLine(); + WriteTryParseNonNumeric(type, parameterName); + WriteLine(); + WriteTryParseLookup(keySelector, type); + } + + private void WriteTryParseNonNumeric(string type, string parameterName = "value") + { + if (Model.IsFlags) + { #line default #line hidden - #line 108 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out "); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" private static bool TryParseNonNumeric"); #line default #line hidden - #line 111 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); #line default #line hidden - #line 111 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParse(value, ignoreCase, throwOnFailure: false, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The case-sensitive string representation of the enumeration name or underlying value to convert.\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("(ReadOnlySpan "); #line default #line hidden - #line 122 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 122 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(", StringComparison comparisonType, bool throwOnFailure, out "); #line default #line hidden - #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" result)\r\n {\r\n bool parsed = true;\r\n "); #line default #line hidden - #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParse(ReadOnlySpan value, out "); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" localResult = 0;\r\n foreach (var item in new FlagsEnumTokenizer("); #line default #line hidden - #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParse(value, ignoreCase: false, throwOnFailure: false, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); + #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("))\r\n {\r\n bool success = TryParseSingle"); #line default #line hidden - #line 139 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 86 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); #line default #line hidden - #line 139 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains null value.\r\n /// \r\n public static "); + #line 86 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("(item, comparisonType, out "); #line default #line hidden - #line 142 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 86 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 142 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write("? TryParse(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n return TryParse(value, ignoreCase, throwOnFailure: false, out "); + #line 86 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" singleValue);\r\n if (!success)\r\n {\r\n parsed = false;\r\n break;\r\n }\r\n\r\n localResult |= singleValue;\r\n }\r\n\r\n if (parsed)\r\n {\r\n result = localResult;\r\n return true;\r\n }\r\n\r\n if (throwOnFailure)\r\n {\r\n ThrowHelper.ThrowValueNotFound("); #line default #line hidden - #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 104 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out "); + #line 104 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(", nameof("); #line default #line hidden - #line 147 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 104 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 147 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" result)\r\n {\r\n var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;\r\n bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out "); + #line 104 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("));\r\n }\r\n\r\n result = 0;\r\n return false;\r\n }\r\n"); #line default #line hidden - #line 150 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + #line 110 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } + else + { #line default #line hidden - #line 150 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(" number);\r\n if (!success)\r\n {\r\n result = 0;\r\n return false;\r\n }\r\n\r\n result = ("); + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" private static bool TryParseNonNumeric"); #line default #line hidden - #line 157 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); #line default #line hidden - #line 157 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" -this.Write(")number;\r\n return true;\r\n }\r\n"); + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("(ReadOnlySpan "); #line default #line hidden - #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" - - } + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" - - private void WriteLegacyDefaultBlock() - { + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(", StringComparison comparisonType, bool throwOnFailure, out "); #line default #line hidden - #line 6 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write("\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// One of the enumeration values that specifies how the strings will be compared.\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" result)\r\n {\r\n bool success = TryParseSingle"); #line default #line hidden - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); + #line 117 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); #line default #line hidden - #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 117 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("("); #line default #line hidden - #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 117 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 117 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(", comparisonType, out result);\r\n if (success)\r\n {\r\n return true;\r\n }\r\n\r\n if (throwOnFailure)\r\n {\r\n ThrowHelper.ThrowValueNotFound("); #line default #line hidden - #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n /// is not a value.\r\n [Obsolete(\"Use TryParse overload with 'ignoreCase' parameter\")]\r\n public static bool TryParse(\r\n [NotNullWhen(true)] string? name,\r\n StringComparison comparisonType,\r\n out "); + #line 125 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 125 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(", nameof("); #line default #line hidden - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" result)\r\n {\r\n bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out "); + #line 125 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(parameterName)); #line default #line hidden - #line 25 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + #line 125 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("));\r\n }\r\n\r\n return false;\r\n }\r\n"); #line default #line hidden - #line 25 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" number);\r\n if (!success)\r\n {\r\n result = 0;\r\n return false;\r\n }\r\n\r\n result = ("); + #line 130 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } + } + + private void WriteTryParseLookup( + Func keySelector, + string type) + { #line default #line hidden - #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 139 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" private static bool TryParseSingle"); #line default #line hidden - #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(")number;\r\n return true;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The case-insensitive string representation of the enumeration name or underlying value to convert.\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 139 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(type)); #line default #line hidden - #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 139 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("(ReadOnlySpan value, StringComparison comparisonType, out "); #line default #line hidden - #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); + #line 139 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 139 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" result)\r\n {\r\n if (value.IsEmpty)\r\n {\r\n"); #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 143 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + var binEmptyValue = Model.Values.FirstOrDefault(x => keySelector(x)?.Length == 0); + if (binEmptyValue != null) + { #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 148 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" result = "); #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n [Obsolete(\"Use TryParse overload with 'ignoreCase' parameter\")]\r\n public static bool TryParseIgnoreCase(\r\n [NotNullWhen(true)] string? name,\r\n out "); + #line 148 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(binEmptyValue.MemberValue)); #line default #line hidden - #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 148 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(";\r\n return true;\r\n"); #line default #line hidden - #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParse(name.AsSpan(), ignoreCase: true, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The case-insensitive string representation of the enumeration name or underlying value to convert.\r\n /// \r\n /// Contains an object of type "); + #line 150 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } + else + { #line default #line hidden - #line 61 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 155 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" result = 0;\r\n return false;\r\n"); #line default #line hidden - #line 61 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains null value.\r\n /// \r\n [Obsolete(\"Use TryParse overload with 'ignoreCase' parameter\")]\r\n public static "); + #line 157 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } #line default #line hidden - #line 65 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" }\r\n\r\n"); #line default #line hidden - #line 65 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write("? TryParseIgnoreCase(string? name)\r\n {\r\n return TryParse(name.AsSpan(), ignoreCase: true, out "); + #line 162 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + var lookupTable = Model.Values.Where(x => keySelector(x)?.Length > 0).ToLookup(x => keySelector(x)![0]); #line default #line hidden - #line 67 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 165 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" switch (value[0])\r\n {\r\n"); #line default #line hidden - #line 67 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// One of the enumeration values that specifies how the strings will be compared.\r\n /// \r\n /// Contains an object of type "); + #line 167 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + foreach (var curr in lookupTable.OrderBy(x => x.Key)) + { + if (char.IsSurrogate(curr.Key) || char.IsControl(curr.Key)) + { #line default #line hidden - #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 173 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" case '\\u"); #line default #line hidden - #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains null value.\r\n /// \r\n /// is not a value.\r\n [Obsolete(\"Use TryParse overload with 'ignoreCase' parameter\")]\r\n public static "); + #line 173 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(((int)curr.Key).ToString("x4"))); #line default #line hidden - #line 82 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 173 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("':\r\n"); #line default #line hidden - #line 82 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write("? TryParse(string? name, StringComparison comparisonType)\r\n {\r\n return TryParse(name, comparisonType, out "); + #line 174 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } + else if (char.ToUpperInvariant(curr.Key) == curr.Key && char.ToLowerInvariant(curr.Key) == curr.Key) + { #line default #line hidden - #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 179 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" case '"); #line default #line hidden - #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n"); + #line 179 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.Key)); #line default #line hidden - #line 86 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\LegacyDefaultBlock.ttinclude" - - } + #line 179 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("':\r\n"); #line default #line hidden - #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 180 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" - private void WriteEnumMemberBlock() - { - if (!Model.HasSerializationValue) - return; + } + else + { #line default #line hidden - #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write("\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified serialized value. Note that this value need not be a member of the "); + #line 185 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" case '"); #line default #line hidden - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 185 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(char.ToUpperInvariant(curr.Key))); #line default #line hidden - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" enumeration.\r\n /// is .\r\n /// is empty or does not represent a valid value.\r\n public static "); + #line 185 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("':\r\n case '"); #line default #line hidden - #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 186 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(char.ToLowerInvariant(curr.Key))); #line default #line hidden - #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" ParseFromEnumMemberValue(string value, bool ignoreCase = false)\r\n {\r\n if (value is null) ThrowArgumentNullException(nameof(value));\r\n TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result);\r\n return result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified serialized value. Note that this value need not be a member of the "); + #line 186 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("':\r\n"); #line default #line hidden - #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 187 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } #line default #line hidden - #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n public static "); + #line 190 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" switch (value)\r\n {\r\n"); #line default #line hidden - #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 192 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + foreach (var enumValue in curr) + { #line default #line hidden - #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" ParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: true, out var result);\r\n return result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified serialized value or null. Note that this value need not be a member of the "); + #line 196 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" case { } when value.Equals(\""); #line default #line hidden - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 196 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(keySelector(enumValue))); #line default #line hidden - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n [return: NotNullIfNotNull(\"value\")]\r\n public static "); + #line 196 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write("\", comparisonType):\r\n result = "); #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 197 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(enumValue.MemberValue)); #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write("? ParseFromEnumMemberValueOrNull(string? value, bool ignoreCase = false)\r\n {\r\n if (value is null) return null;\r\n TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result);\r\n return result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 197 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(";\r\n return true;\r\n"); #line default #line hidden - #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 199 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } #line default #line hidden - #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" whose value is represented by a\r\n /// serialized value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); + #line 202 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" }\r\n break;\r\n"); #line default #line hidden - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 204 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" + + } #line default #line hidden - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 207 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" +this.Write(" }\r\n\r\n result = 0;\r\n return false;\r\n }\r\n"); #line default #line hidden - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 212 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\TryParseInternal.ttinclude" - - #line default - #line hidden - - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, bool ignoreCase, out "); + } #line default #line hidden - #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" + + private void WriteDefaultBlock() + { #line default #line hidden - #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 5 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified name or numeric value. Note that this value need not be a member of the "); #line default #line hidden - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" whose value is represented by a\r\n /// serialized value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" enumeration.\r\n /// is .\r\n /// is empty or does not represent a valid value.\r\n public static "); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 14 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 14 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" Parse(string value, bool ignoreCase = false)\r\n {\r\n if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value));\r\n TryParseName(value.AsSpan(), "); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, out "); + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: true, out var result);\r\n return ("); #line default #line hidden - #line 79 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 18 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 79 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The value as defined with .\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); + #line 18 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified name or numeric value. Note that this value need not be a member of the "); #line default #line hidden - #line 90 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 90 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains a null value.\r\n /// \r\n public static "); + #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n public static "); #line default #line hidden - #line 93 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 93 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write("? TryParseFromEnumMemberValue(string? value, bool ignoreCase = false)\r\n {\r\n return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out "); + #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" Parse(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n TryParseName(value, "); #line default #line hidden - #line 95 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 31 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 95 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 31 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: true, out var result);\r\n return ("); #line default #line hidden - #line 105 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 105 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" whose value is represented by a\r\n /// serialized value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified name or numeric value or null. Note that this value need not be a member of the "); #line default #line hidden - #line 107 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 107 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n [return: NotNullIfNotNull(\"value\")]\r\n public static "); #line default #line hidden - #line 107 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 107 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, out "); + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("? ParseOrNull(string? value, bool ignoreCase = false)\r\n {\r\n if (value is null) return null;\r\n TryParseName(value.AsSpan(), "); #line default #line hidden - #line 110 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 47 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 110 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 47 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: true, out var result);\r\n return ("); #line default #line hidden - #line 121 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 121 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" whose value is represented by a\r\n /// serialized value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); #line default #line hidden - #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); #line default #line hidden - #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out "); + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParseFromEnumMemberValue(value, ignoreCase: false, throwOnFailure: false, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The value as defined with .\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out "); #line default #line hidden - #line 137 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 137 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains a null value.\r\n /// \r\n public static "); + #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseName(value.AsSpan(), "); #line default #line hidden - #line 140 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 140 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write("? TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out "); + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 142 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 142 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out "); + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", "); #line default #line hidden - #line 145 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 145 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParseFromEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure, out result);\r\n }\r\n\r\n private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out "); + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// \r\n /// When this method returns, result contains an object of type "); #line default #line hidden - #line 150 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 150 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result)\r\n {\r\n bool success = EnumStringParser.TryParse(value, s_serializationStringParser, comparisonType, throwOnFailure, out "); + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); #line default #line hidden - #line 152 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 152 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" number);\r\n if (!success)\r\n {\r\n result = 0;\r\n return false;\r\n }\r\n\r\n result = ("); + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 159 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 159 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(")number;\r\n return true;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// One of the enumeration values that specifies how the strings will be compared.\r\n /// \r\n /// When this method returns, result contains an object of type "); + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParse([NotNullWhen(true)] string? value, out "); #line default #line hidden - #line 170 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 170 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseName(value.AsSpan(), "); #line default #line hidden - #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetComparisonExpression(false))); #line default #line hidden - #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(". Note that this value need not be a member of the "); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n /// is not a value.\r\n [Obsolete(\"Use TryParseFromEnumMemberValue overload with 'ignoreCase' parameter\")]\r\n public static bool TryParseFromEnumMemberValue(\r\n [NotNullWhen(true)] string? value,\r\n StringComparison comparisonType,\r\n out "); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", "); #line default #line hidden - #line 180 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 180 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out result);\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the value associated with one enumerated constant to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The value as defined with .\r\n /// One of the enumeration values that specifies how the strings will be compared.\r\n /// \r\n /// Contains an object of type "); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); #line default #line hidden - #line 192 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 93 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 192 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains a null value.\r\n /// \r\n /// is not a value.\r\n [Obsolete(\"Use TryParseFromEnumMemberValue overload with 'ignoreCase' parameter\")]\r\n public static "); + #line 93 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains null value.\r\n /// \r\n public static "); #line default #line hidden - #line 197 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + #line 96 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 197 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write("? TryParseFromEnumMemberValue(string? value, StringComparison comparisonType)\r\n {\r\n return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out "); + #line 96 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("? TryParse(string? value, bool ignoreCase = false)\r\n {\r\n return TryParseName(value.AsSpan(), "); #line default #line hidden - #line 199 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 98 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 199 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n"); + #line 98 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: false, out var result) ? ("); #line default #line hidden - #line 201 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" - - } + #line 98 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" + #line 98 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); - private void WriteDescriptionBlock() - { - if (!Model.HasDescription) - return; + + #line default + #line hidden + + #line 108 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write("\r\n public static "); + #line 108 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); #line default #line hidden - #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 110 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" CreateFromDescription(string description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n if (description is null) ThrowArgumentNullException(nameof(description));\r\n TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result);\r\n return result;\r\n }\r\n\r\n public static "); + #line 110 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 110 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" CreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n TryCreateFromDescription(description, comparisonType, throwOnFailure: true, out var result);\r\n return result;\r\n }\r\n\r\n [return: NotNullIfNotNull(\"description\")]\r\n public static "); + #line 110 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out "); #line default #line hidden - #line 22 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" + #line 113 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 22 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write("? CreateFromDescriptionOrNull(string? description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n if (description is null) return null;\r\n TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result);\r\n return result;\r\n }\r\n\r\n public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, StringComparison comparisonType, out "); + #line 113 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseName(value, "); #line default #line hidden - #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out result);\r\n }\r\n\r\n public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, out "); + #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" + #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryCreateFromDescription(description.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out result);\r\n }\r\n\r\n public static "); + #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", "); #line default #line hidden - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write("? TryCreateFromDescription(string? description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n return TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out "); + #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The case-sensitive string representation of the enumeration name or underlying value to convert.\r\n /// \r\n /// When this method returns, result contains an object of type "); #line default #line hidden - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 125 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n public static bool TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType, out "); + #line 125 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryCreateFromDescription(description, comparisonType, throwOnFailure: false, out result);\r\n }\r\n\r\n public static bool TryCreateFromDescription(ReadOnlySpan description, out "); + #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryCreateFromDescription(description, StringComparison.Ordinal, throwOnFailure: false, out result);\r\n }\r\n\r\n public static "); + #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParse(ReadOnlySpan value, out "); #line default #line hidden - #line 54 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" + #line 130 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 54 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write("? TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n return TryCreateFromDescription(description, comparisonType, throwOnFailure: false, out "); + #line 130 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseName(value, "); #line default #line hidden - #line 56 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 133 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetComparisonExpression(false))); #line default #line hidden - #line 56 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n private static bool TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType, bool throwOnFailure, out "); + #line 133 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 59 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" + #line 133 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 59 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" result)\r\n {\r\n bool success = EnumStringParser.TryParseDescription(description, s_stringParser, comparisonType, throwOnFailure, out "); + #line 133 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", "); #line default #line hidden - #line 61 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" + #line 133 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 61 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(" number);\r\n if (!success)\r\n {\r\n result = 0;\r\n return false;\r\n }\r\n\r\n result = ("); + #line 133 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); #line default #line hidden - #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 143 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" -this.Write(")number;\r\n return true;\r\n }\r\n"); + #line 143 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains null value.\r\n /// \r\n public static "); #line default #line hidden - #line 71 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" - - } + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("? TryParse(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n return TryParseName(value, "); - private void WriteDisplayBlock() - { - if (Model.HasDisplayName) - { + + #line default + #line hidden + + #line 148 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write("\r\n public static bool TryCreateFromDisplayShortName(\r\n [NotNullWhen(true)] string? displayShortName,\r\n StringComparison comparisonType,\r\n out "); + #line 148 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: false, out var result) ? ("); #line default #line hidden - #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 148 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result)\r\n {\r\n"); + #line 148 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n\r\n"); #line default #line hidden - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 151 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" - if (Model.Values.All(x => x.Display?.ShortName == null)) - { + WriteTryParse(x => x.MemberName, "Name"); #line default #line hidden - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" return TryCreateFromDisplayName(displayShortName, comparisonType, out result);\r\n"); + #line 155 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// One of the enumeration values that specifies how the strings will be compared.\r\n /// \r\n /// When this method returns, result contains an object of type "); #line default #line hidden - #line 18 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" - - } - else - { + #line 162 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" "); + #line 162 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); #line default #line hidden - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + #line 164 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" numValue;\r\n switch (displayShortName)\r\n {\r\n"); + #line 164 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" - - foreach (var curr in Model.Values.Where(x => x.Display?.ShortName != null)) - { + #line 164 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" case { } s when s.Equals("); + #line 164 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n /// is not a value.\r\n [Obsolete(\"Use TryParse overload with 'ignoreCase' parameter\")]\r\n public static bool TryParse(\r\n [NotNullWhen(true)] string? name,\r\n StringComparison comparisonType,\r\n out "); #line default #line hidden - #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.Display!.ResourceShortName != null - ? Append(curr.Display.ResourceShortName) - : Append($"\"{curr.Display.ShortName}\""))); + #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(", comparisonType):\r\n numValue = "); + #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + #line 175 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(";\r\n break;\r\n"); + #line 175 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", "); #line default #line hidden - #line 36 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" - - } + #line 175 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" default:\r\n return TryCreateFromDisplayName(displayShortName, comparisonType, out result);\r\n }\r\n\r\n result = ("); + #line 175 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object. The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The case-insensitive string representation of the enumeration name or underlying value to convert.\r\n /// \r\n /// When this method returns, result contains an object of type "); #line default #line hidden - #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 184 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(")numValue;\r\n return true;\r\n"); + #line 184 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); #line default #line hidden - #line 45 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" - - } + #line 186 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" }\r\n\r\n public static bool TryCreateFromDisplayShortName([NotNullWhen(true)] string? displayShortName, out "); + #line 186 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 186 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryCreateFromDisplayShortName(displayShortName, StringComparison.Ordinal, out result);\r\n }\r\n\r\n public static "); + #line 186 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n [Obsolete(\"Use TryParse overload with 'ignoreCase' parameter\")]\r\n public static bool TryParseIgnoreCase(\r\n [NotNullWhen(true)] string? name,\r\n out "); #line default #line hidden - #line 55 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 192 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 55 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write("? TryCreateFromDisplayShortName(string? displayShortName, StringComparison comparisonType)\r\n {\r\n return TryCreateFromDisplayShortName(displayShortName, comparisonType, out "); + #line 192 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseName(name.AsSpan(), "); #line default #line hidden - #line 57 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 195 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetComparisonExpression(true))); #line default #line hidden - #line 57 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n public static "); + #line 195 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 195 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 195 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 195 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 195 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The case-insensitive string representation of the enumeration name or underlying value to convert.\r\n /// \r\n /// Contains an object of type "); + + + #line default + #line hidden + + #line 204 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 204 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains null value.\r\n /// \r\n [Obsolete(\"Use TryParse overload with 'ignoreCase' parameter\")]\r\n public static "); + + + #line default + #line hidden + + #line 208 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 208 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("? TryParseIgnoreCase(string? name)\r\n {\r\n return TryParseName(name.AsSpan(), "); + + + #line default + #line hidden + + #line 210 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetComparisonExpression(true))); + + + #line default + #line hidden + + #line 210 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(", throwOnFailure: false, out var result) ? ("); + + + #line default + #line hidden + + #line 210 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 210 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the name or numeric value of one or more enumerated constants to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration name or underlying value to convert.\r\n /// One of the enumeration values that specifies how the strings will be compared.\r\n /// \r\n /// Contains an object of type "); + + + #line default + #line hidden + + #line 220 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 220 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains null value.\r\n /// \r\n /// is not a value.\r\n [Obsolete(\"Use TryParse overload with 'ignoreCase' parameter\")]\r\n public static "); + + + #line default + #line hidden + + #line 225 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 225 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("? TryParse(string? name, StringComparison comparisonType)\r\n {\r\n return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? ("); + + + #line default + #line hidden + + #line 227 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 227 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n"); + + + #line default + #line hidden + + #line 229 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DefaultBlock.ttinclude" + + } + + + #line default + #line hidden + + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + + private void WriteEnumMemberBlock() + { + if (!Model.HasSerializationValue) + return; + + + #line default + #line hidden + + #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write("\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified serialized value. Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" enumeration.\r\n /// is .\r\n /// is empty or does not represent a valid value.\r\n public static "); + + + #line default + #line hidden + + #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" ParseFromEnumMemberValue(string value, bool ignoreCase = false)\r\n {\r\n if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value));\r\n TryParseEnumMemberValue(value.AsSpan(), "); + + + #line default + #line hidden + + #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); + + + #line default + #line hidden + + #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", throwOnFailure: true, out var result);\r\n return ("); + + + #line default + #line hidden + + #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified serialized value. Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n public static "); + + + #line default + #line hidden + + #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" ParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n TryParseEnumMemberValue(value, "); + + + #line default + #line hidden + + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); + + + #line default + #line hidden + + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", throwOnFailure: true, out var result);\r\n return ("); + + + #line default + #line hidden + + #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified serialized value or null. Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n [return: NotNullIfNotNull(\"value\")]\r\n public static "); + + + #line default + #line hidden + + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write("? ParseFromEnumMemberValueOrNull(string? value, bool ignoreCase = false)\r\n {\r\n if (value is null) return null;\r\n TryParseEnumMemberValue(value.AsSpan(), "); + + + #line default + #line hidden + + #line 47 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); + + + #line default + #line hidden + + #line 47 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", throwOnFailure: true, out var result);\r\n return ("); + + + #line default + #line hidden + + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); + + + #line default + #line hidden + + #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" whose value is represented by a\r\n /// serialized value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); + + + #line default + #line hidden + + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, bool ignoreCase, out "); + + + #line default + #line hidden + + #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseEnumMemberValue(value.AsSpan(), "); + + + #line default + #line hidden + + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); + + + #line default + #line hidden + + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); + + + #line default + #line hidden + + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// \r\n /// When this method returns, result contains an object of type "); + + + #line default + #line hidden + + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" whose value is represented by a\r\n /// serialized value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); + + + #line default + #line hidden + + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, out "); + + + #line default + #line hidden + + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseEnumMemberValue(value.AsSpan(), "); + + + #line default + #line hidden + + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetComparisonExpression(false))); + + + #line default + #line hidden + + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); + + + #line default + #line hidden + + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The value as defined with .\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); + + + #line default + #line hidden + + #line 92 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 92 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains a null value.\r\n /// \r\n public static "); + + + #line default + #line hidden + + #line 95 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 95 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write("? TryParseFromEnumMemberValue(string? value, bool ignoreCase = false)\r\n {\r\n return TryParseEnumMemberValue(value.AsSpan(), "); + + + #line default + #line hidden + + #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); + + + #line default + #line hidden + + #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", throwOnFailure: false, out var result) ? ("); + + + #line default + #line hidden + + #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); + + + #line default + #line hidden + + #line 107 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 107 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" whose value is represented by a\r\n /// serialized value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); + + + #line default + #line hidden + + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, out "); + + + #line default + #line hidden + + #line 112 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 112 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseEnumMemberValue(value, "); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// \r\n /// When this method returns, result contains an object of type "); + + + #line default + #line hidden + + #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" whose value is represented by a\r\n /// serialized value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); + + + #line default + #line hidden + + #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out "); + + + #line default + #line hidden + + #line 129 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 129 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseEnumMemberValue(value, "); + + + #line default + #line hidden + + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetComparisonExpression(false))); + + + #line default + #line hidden + + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); + + + #line default + #line hidden + + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// \r\n /// The value as defined with .\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); + + + #line default + #line hidden + + #line 141 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 141 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains a null value.\r\n /// \r\n public static "); + + + #line default + #line hidden + + #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write("? TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n return TryParseEnumMemberValue(value, "); + + + #line default + #line hidden + + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); + + + #line default + #line hidden + + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", throwOnFailure: false, out var result) ? ("); + + + #line default + #line hidden + + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n\r\n"); + + + #line default + #line hidden + + #line 149 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + + WriteTryParse(x => x.ResolvedSerializedValue, "EnumMemberValue"); + + + #line default + #line hidden + + #line 153 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write("\r\n /// \r\n /// Converts the string representation of the serialized value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The value as defined with .\r\n /// One of the enumeration values that specifies how the strings will be compared.\r\n /// \r\n /// When this method returns, result contains an object of type "); + + + #line default + #line hidden + + #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" whose value is represented by value\r\n /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the\r\n /// underlying type of "); + + + #line default + #line hidden + + #line 162 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 162 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 162 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 162 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n /// is not a value.\r\n [Obsolete(\"Use TryParseFromEnumMemberValue overload with 'ignoreCase' parameter\")]\r\n public static bool TryParseFromEnumMemberValue(\r\n [NotNullWhen(true)] string? value,\r\n StringComparison comparisonType,\r\n out "); + + + #line default + #line hidden + + #line 170 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 170 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As<"); + + + #line default + #line hidden + + #line 173 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 173 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 173 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 173 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the value associated with one enumerated constant to\r\n /// an equivalent enumerated object.\r\n /// \r\n /// The value as defined with .\r\n /// One of the enumeration values that specifies how the strings will be compared.\r\n /// \r\n /// Contains an object of type "); + + + #line default + #line hidden + + #line 183 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 183 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains a null value.\r\n /// \r\n /// is not a value.\r\n [Obsolete(\"Use TryParseFromEnumMemberValue overload with 'ignoreCase' parameter\")]\r\n public static "); + + + #line default + #line hidden + + #line 188 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 188 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write("? TryParseFromEnumMemberValue(string? value, StringComparison comparisonType)\r\n {\r\n return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? ("); + + + #line default + #line hidden + + #line 190 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 190 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n"); + + + #line default + #line hidden + + #line 192 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\EnumMemberBlock.ttinclude" + + } + + + #line default + #line hidden + + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" + + private void WriteDescriptionBlock() + { + if (!Model.HasDescription) + return; + + + #line default + #line hidden + + #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write("\r\n public static "); + + + #line default + #line hidden + + #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(" CreateFromDescription(string description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n if (description is null) ThrowHelper.ThrowArgumentNullException(nameof(description));\r\n TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result);\r\n return ("); + + + #line default + #line hidden + + #line 12 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 12 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n public static "); + + + #line default + #line hidden + + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(" CreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n TryParseDescription(description, comparisonType, throwOnFailure: true, out var result);\r\n return ("); + + + #line default + #line hidden + + #line 18 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 18 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n [return: NotNullIfNotNull(\"description\")]\r\n public static "); + + + #line default + #line hidden + + #line 22 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 22 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write("? CreateFromDescriptionOrNull(string? description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n if (description is null) return null;\r\n TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result);\r\n return ("); + + + #line default + #line hidden + + #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, StringComparison comparisonType, out "); + + + #line default + #line hidden + + #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As<"); + + + #line default + #line hidden + + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, out "); + + + #line default + #line hidden + + #line 35 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 35 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseDescription(description.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As<"); + + + #line default + #line hidden + + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n public static "); + + + #line default + #line hidden + + #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write("? TryCreateFromDescription(string? description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n return TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? ("); + + + #line default + #line hidden + + #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n\r\n public static bool TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType, out "); + + + #line default + #line hidden + + #line 46 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 46 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseDescription(description, comparisonType, throwOnFailure: false, out Unsafe.As<"); + + + #line default + #line hidden + + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n public static bool TryCreateFromDescription(ReadOnlySpan description, out "); + + + #line default + #line hidden + + #line 52 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 52 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseDescription(description, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As<"); + + + #line default + #line hidden + + #line 55 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 55 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(", "); + + + #line default + #line hidden + + #line 55 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 55 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n public static "); + + + #line default + #line hidden + + #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write("? TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal)\r\n {\r\n return TryParseDescription(description, comparisonType, throwOnFailure: false, out var result) ? ("); + + + #line default + #line hidden + + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n\r\n"); + + + #line default + #line hidden + + #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DescriptionBlock.ttinclude" + + WriteTryParse(x => x.Description, "Description", "description", allowNumbers: false); + } + + + #line default + #line hidden + + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + private void WriteDisplayBlock() + { + if (Model.HasDisplayName) + { + + + #line default + #line hidden + + #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write("\r\n public static bool TryCreateFromDisplayShortName(\r\n [NotNullWhen(true)] string? displayShortName,\r\n StringComparison comparisonType,\r\n out "); + + + #line default + #line hidden + + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result)\r\n {\r\n"); + + + #line default + #line hidden + + #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + if (Model.Values.All(x => x.Display?.ShortName == null)) + { + + + #line default + #line hidden + + #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" return TryCreateFromDisplayName(displayShortName, comparisonType, out result);\r\n"); + + + #line default + #line hidden + + #line 18 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + else + { + + + #line default + #line hidden + + #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" "); + + + #line default + #line hidden + + #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" numValue;\r\n switch (displayShortName)\r\n {\r\n"); + + + #line default + #line hidden + + #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + foreach (var curr in Model.Values.Where(x => x.Display?.ShortName != null)) + { + + + #line default + #line hidden + + #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" case { } s when s.Equals("); + + + #line default + #line hidden + + #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.Display!.ResourceShortName != null + ? Append(curr.Display.ResourceShortName) + : Append($"\"{curr.Display.ShortName}\""))); + + + #line default + #line hidden + + #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(", comparisonType):\r\n numValue = "); + + + #line default + #line hidden + + #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(";\r\n break;\r\n"); + + + #line default + #line hidden + + #line 36 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + + + #line default + #line hidden + + #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" default:\r\n return TryCreateFromDisplayName(displayShortName, comparisonType, out result);\r\n }\r\n\r\n result = ("); + + + #line default + #line hidden + + #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(")numValue;\r\n return true;\r\n"); + + + #line default + #line hidden + + #line 45 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + + + #line default + #line hidden + + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" }\r\n\r\n public static bool TryCreateFromDisplayShortName([NotNullWhen(true)] string? displayShortName, out "); + + + #line default + #line hidden + + #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result)\r\n {\r\n return TryCreateFromDisplayShortName(displayShortName, StringComparison.Ordinal, out result);\r\n }\r\n\r\n public static "); + + + #line default + #line hidden + + #line 55 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 55 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write("? TryCreateFromDisplayShortName(string? displayShortName, StringComparison comparisonType)\r\n {\r\n return TryCreateFromDisplayShortName(displayShortName, comparisonType, out "); + + + #line default + #line hidden + + #line 57 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 57 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result) ? result : null;\r\n }\r\n\r\n public static "); + + + #line default + #line hidden + + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" this.Write("? TryCreateFromDisplayShortName(string? displayShortName)\r\n {\r\n return TryCreateFromDisplayShortName(displayShortName, StringComparison.Ordinal, out "); #line default #line hidden - #line 62 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 62 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 62 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result) ? result : null;\r\n }\r\n\r\n public static bool TryCreateFromDisplayName(\r\n [NotNullWhen(true)] string? displayName,\r\n StringComparison comparisonType,\r\n out "); + + + #line default + #line hidden + + #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result)\r\n {\r\n"); + + + #line default + #line hidden + + #line 70 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + if (Model.Values.Count == 0) + { + + + #line default + #line hidden + + #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result = default;\r\n return false;\r\n"); + + + #line default + #line hidden + + #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + else + { + + + #line default + #line hidden + + #line 81 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" "); + + + #line default + #line hidden + + #line 81 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 81 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" numValue;\r\n switch (displayName)\r\n {\r\n"); + + + #line default + #line hidden + + #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + foreach (var curr in Model.Values) + { + + + #line default + #line hidden + + #line 88 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" case { } s when s.Equals("); + + + #line default + #line hidden + + #line 88 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.Display?.ResourceName != null + ? Append(curr.Display.ResourceName) + : curr.Display?.Name != null + ? Append($"\"{curr.Display.Name}\"") + : Append($"\"{curr.MemberName}\""))); + + + #line default + #line hidden + + #line 93 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(", comparisonType):\r\n numValue = "); + + + #line default + #line hidden + + #line 94 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 94 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(";\r\n break;\r\n"); + + + #line default + #line hidden + + #line 96 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + + + #line default + #line hidden + + #line 99 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" default:\r\n result = default;\r\n return false;\r\n }\r\n\r\n result = ("); + + + #line default + #line hidden + + #line 104 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 104 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(")numValue;\r\n return true;\r\n"); + + + #line default + #line hidden + + #line 106 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + + + #line default + #line hidden + + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" }\r\n\r\n public static bool TryCreateFromDisplayName([NotNullWhen(true)] string? displayName, out "); + + + #line default + #line hidden + + #line 111 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 111 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result)\r\n {\r\n return TryCreateFromDisplayName(displayName, StringComparison.Ordinal, out result);\r\n }\r\n\r\n public static "); + + + #line default + #line hidden + + #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write("? TryCreateFromDisplayName(string? displayName, StringComparison comparisonType)\r\n {\r\n return TryCreateFromDisplayName(displayName, comparisonType, out "); + + + #line default + #line hidden + + #line 118 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 118 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result) ? result : null;\r\n }\r\n\r\n public static "); + + + #line default + #line hidden + + #line 121 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 121 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write("? TryCreateFromDisplayName(string? displayName)\r\n {\r\n return TryCreateFromDisplayName(displayName, StringComparison.Ordinal, out "); + + + #line default + #line hidden + + #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result) ? result : null;\r\n }\r\n"); + + + #line default + #line hidden + + #line 125 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + + + #line default + #line hidden + + #line 128 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + if (Model.HasDisplayDescription) + { + + + #line default + #line hidden + + #line 133 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write("\r\n public static bool TryCreateFromDescription(\r\n [NotNullWhen(true)] string? description,\r\n StringComparison comparisonType,\r\n out "); + + + #line default + #line hidden + + #line 136 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 136 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result)\r\n {\r\n"); + + + #line default + #line hidden + + #line 138 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + if (Model.Values.All(x => x.Display?.Description == null)) + { + + + #line default + #line hidden + + #line 142 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result = default;\r\n return false;\r\n"); + + + #line default + #line hidden + + #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + else + { + + + #line default + #line hidden + + #line 149 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" "); + + + #line default + #line hidden + + #line 149 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 149 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" numValue;\r\n switch (description)\r\n {\r\n"); + + + #line default + #line hidden + + #line 152 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + foreach (var curr in Model.Values.Where(x => x.Display?.Description != null)) + { + + + #line default + #line hidden + + #line 156 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" case { } s when s.Equals("); + + + #line default + #line hidden + + #line 156 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.Display!.ResourceDescription != null + ? Append(curr.Display.ResourceDescription) + : Append($"\"{curr.Display.Description}\""))); + + + #line default + #line hidden + + #line 159 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(", comparisonType):\r\n numValue = "); + + + #line default + #line hidden + + #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + + + #line default + #line hidden + + #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(";\r\n break;\r\n"); + + + #line default + #line hidden + + #line 162 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + + + #line default + #line hidden + + #line 165 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" default:\r\n result = default;\r\n return false;\r\n }\r\n\r\n result = ("); + + + #line default + #line hidden + + #line 170 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 170 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(")numValue;\r\n return true;\r\n"); + + + #line default + #line hidden + + #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + + + #line default + #line hidden + + #line 175 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" }\r\n\r\n public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, out "); + + + #line default + #line hidden + + #line 177 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 177 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result)\r\n {\r\n return TryCreateFromDescription(description, StringComparison.Ordinal, out result);\r\n }\r\n\r\n public static "); + + + #line default + #line hidden + + #line 182 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 182 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write("? TryCreateFromDescription(string? description, StringComparison comparisonType)\r\n {\r\n return TryCreateFromDescription(description, comparisonType, out "); + + + #line default + #line hidden + + #line 184 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 184 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result) ? result : null;\r\n }\r\n\r\n public static "); + + + #line default + #line hidden + + #line 187 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 187 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write("? TryCreateFromDescription(string? description)\r\n {\r\n return TryCreateFromDescription(description, StringComparison.Ordinal, out "); + + + #line default + #line hidden + + #line 189 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 189 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" +this.Write(" result) ? result : null;\r\n }\r\n"); + + + #line default + #line hidden + + #line 191 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + + } + } + + + #line default + #line hidden + + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" + + public void WriteJsonBlock() + { + if (!Model.HasJsonProperty && (Model.SelectedGenerators & SelectedGenerators.JsonConverter) == 0) + return; + + + #line default + #line hidden + + #line 8 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write("\r\n /// \r\n /// Converts the string representation of the serialized JSON value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized JSON value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified serialized value. Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" enumeration.\r\n /// is .\r\n /// is empty or does not represent a valid value.\r\n public static "); + + + #line default + #line hidden + + #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 16 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" ParseJsonString(string value, bool ignoreCase = false)\r\n {\r\n if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value));\r\n TryParseJsonString(value.AsSpan(), "); + + + #line default + #line hidden + + #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); + + + #line default + #line hidden + + #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", throwOnFailure: true, out var result);\r\n return ("); + + + #line default + #line hidden + + #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized JSON value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized JSON value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified serialized value. Note that this value need not be a member of the "); + + + #line default + #line hidden + + #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n public static "); + + + #line default + #line hidden + + #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + + + #line default + #line hidden + + #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" ParseJsonString(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n TryParseJsonString(value, "); + + + #line default + #line hidden + + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 62 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n public static bool TryCreateFromDisplayName(\r\n [NotNullWhen(true)] string? displayName,\r\n StringComparison comparisonType,\r\n out "); + #line 32 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", throwOnFailure: true, out var result);\r\n return ("); #line default #line hidden - #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result)\r\n {\r\n"); + #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized JSON value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized JSON value to convert.\r\n /// to ignore case; to regard case.\r\n /// The value represented by the specified serialized value or null. Note that this value need not be a member of the "); #line default #line hidden - #line 70 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); - if (Model.Values.Count == 0) - { + + #line default + #line hidden + + #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" enumeration.\r\n /// is empty or does not represent a valid value.\r\n [return: NotNullIfNotNull(\"value\")]\r\n public static "); #line default #line hidden - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result = default;\r\n return false;\r\n"); + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write("? ParseJsonStringOrNull(string? value, bool ignoreCase = false)\r\n {\r\n if (value is null) return null;\r\n TryParseJsonString(value.AsSpan(), "); - } - else - { + + #line default + #line hidden + + #line 47 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 81 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" "); + #line 47 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", throwOnFailure: true, out var result);\r\n return ("); #line default #line hidden - #line 81 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 81 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" numValue;\r\n switch (displayName)\r\n {\r\n"); + #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(")result;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized JSON value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration serialized JSON value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); #line default #line hidden - #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); - foreach (var curr in Model.Values) - { + + #line default + #line hidden + + #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" whose value is represented by a\r\n /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); #line default #line hidden - #line 88 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" case { } s when s.Equals("); + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 88 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.Display?.ResourceName != null - ? Append(curr.Display.ResourceName) - : curr.Display?.Name != null - ? Append($"\"{curr.Display.Name}\"") - : Append($"\"{curr.MemberName}\""))); + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 93 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(", comparisonType):\r\n numValue = "); + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 94 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseJsonString([NotNullWhen(true)] string? value, bool ignoreCase, out "); #line default #line hidden - #line 94 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(";\r\n break;\r\n"); + #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 96 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseJsonString(value.AsSpan(), "); - } + + #line default + #line hidden + + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 99 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" default:\r\n result = default;\r\n return false;\r\n }\r\n\r\n result = ("); + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 104 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 104 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(")numValue;\r\n return true;\r\n"); + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", "); #line default #line hidden - #line 106 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - } + + #line default + #line hidden + + #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized JSON value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration serialized JSON value to convert.\r\n /// \r\n /// When this method returns, result contains an object of type "); #line default #line hidden - #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" }\r\n\r\n public static bool TryCreateFromDisplayName([NotNullWhen(true)] string? displayName, out "); + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 111 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" whose value is represented by a\r\n /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); #line default #line hidden - #line 111 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryCreateFromDisplayName(displayName, StringComparison.Ordinal, out result);\r\n }\r\n\r\n public static "); + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 116 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write("? TryCreateFromDisplayName(string? displayName, StringComparison comparisonType)\r\n {\r\n return TryCreateFromDisplayName(displayName, comparisonType, out "); + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 118 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseJsonString([NotNullWhen(true)] string? value, out "); + + + #line default + #line hidden + + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 118 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n public static "); + #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseJsonString(value.AsSpan(), "); #line default #line hidden - #line 121 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetComparisonExpression(false))); #line default #line hidden - #line 121 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write("? TryCreateFromDisplayName(string? displayName)\r\n {\r\n return TryCreateFromDisplayName(displayName, StringComparison.Ordinal, out "); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n"); + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", "); #line default #line hidden - #line 125 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" - - } + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 128 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized JSON value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized JSON value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); - if (Model.HasDisplayDescription) - { + + #line default + #line hidden + + #line 92 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 133 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write("\r\n public static bool TryCreateFromDescription(\r\n [NotNullWhen(true)] string? description,\r\n StringComparison comparisonType,\r\n out "); + #line 92 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains a null value.\r\n /// \r\n public static "); #line default #line hidden - #line 136 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 95 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 136 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result)\r\n {\r\n"); + #line 95 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write("? TryParseJsonString(string? value, bool ignoreCase = false)\r\n {\r\n return TryParseJsonString(value.AsSpan(), "); #line default #line hidden - #line 138 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); - if (Model.Values.All(x => x.Display?.Description == null)) - { + + #line default + #line hidden + + #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", throwOnFailure: false, out var result) ? ("); #line default #line hidden - #line 142 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result = default;\r\n return false;\r\n"); + #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized JSON value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration serialized JSON value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// When this method returns, result contains an object of type "); - } - else - { + + #line default + #line hidden + + #line 107 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 149 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" "); + #line 107 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" whose value is represented by a\r\n /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); #line default #line hidden - #line 149 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 149 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" numValue;\r\n switch (description)\r\n {\r\n"); + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 152 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); - foreach (var curr in Model.Values.Where(x => x.Display?.Description != null)) - { + + #line default + #line hidden + + #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseJsonString(ReadOnlySpan value, bool ignoreCase, out "); #line default #line hidden - #line 156 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" case { } s when s.Equals("); + #line 112 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 156 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.Display!.ResourceDescription != null - ? Append(curr.Display.ResourceDescription) - : Append($"\"{curr.Display.Description}\""))); + #line 112 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseJsonString(value, "); #line default #line hidden - #line 159 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(", comparisonType):\r\n numValue = "); + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); #line default #line hidden - #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(";\r\n break;\r\n"); + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 162 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", "); - } + + #line default + #line hidden + + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - #line 165 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" default:\r\n result = default;\r\n return false;\r\n }\r\n\r\n result = ("); + #line 115 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized JSON value to an equivalent enumerated object.\r\n /// The return value indicates whether the conversion succeeded.\r\n /// \r\n /// The string representation of the enumeration serialized JSON value to convert.\r\n /// \r\n /// When this method returns, result contains an object of type "); #line default #line hidden - #line 170 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 170 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(")numValue;\r\n return true;\r\n"); + #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" whose value is represented by a\r\n /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default\r\n /// value of the underlying type of "); #line default #line hidden - #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); - } + + #line default + #line hidden + + #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(". Note that this value need not be a member of the "); #line default #line hidden - #line 175 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" }\r\n\r\n public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, out "); + #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - #line 177 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 126 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" enumeration.\r\n /// \r\n /// true if the value parameter was converted successfully; otherwise, false.\r\n public static bool TryParseJsonString(ReadOnlySpan value, out "); + + + #line default + #line hidden + + #line 129 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 177 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result)\r\n {\r\n return TryCreateFromDescription(description, StringComparison.Ordinal, out result);\r\n }\r\n\r\n public static "); + #line 129 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" result)\r\n {\r\n Unsafe.SkipInit(out result);\r\n return TryParseJsonString(value, "); #line default #line hidden - #line 182 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetComparisonExpression(false))); #line default #line hidden - #line 182 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write("? TryCreateFromDescription(string? description, StringComparison comparisonType)\r\n {\r\n return TryCreateFromDescription(description, comparisonType, out "); + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", throwOnFailure: false, out Unsafe.As<"); #line default #line hidden - #line 184 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 184 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n\r\n public static "); + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", "); #line default #line hidden - #line 187 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + + + #line default + #line hidden + + #line 132 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(">(ref result));\r\n }\r\n\r\n /// \r\n /// Converts the string representation of the serialized JSON value to an equivalent enumerated object.\r\n /// \r\n /// The string representation of the enumeration serialized JSON value to convert.\r\n /// to ignore case; to regard case.\r\n /// \r\n /// Contains an object of type "); + + + #line default + #line hidden + + #line 141 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + + + #line default + #line hidden + + #line 141 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(" whose value is represented by value if the parse operation succeeds.\r\n /// If the parse operation fails, result contains a null value.\r\n /// \r\n public static "); + + + #line default + #line hidden + + #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 187 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write("? TryCreateFromDescription(string? description)\r\n {\r\n return TryCreateFromDescription(description, StringComparison.Ordinal, out "); + #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write("? TryParseJsonString(ReadOnlySpan value, bool ignoreCase = false)\r\n {\r\n return TryParseJsonString(value, "); #line default #line hidden - #line 189 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(GetIgnoreCaseToComparisonExpression())); + + + #line default + #line hidden + + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write(", throwOnFailure: false, out var result) ? ("); + + + #line default + #line hidden + + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - #line 189 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" -this.Write(" result) ? result : null;\r\n }\r\n"); + #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" +this.Write("?)result : null;\r\n }\r\n\r\n"); #line default #line hidden - #line 191 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\DisplayBlock.ttinclude" + #line 149 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\JsonBlock.ttinclude" - } + WriteTryParse(x => x.ResolvedJsonValue, "JsonString", allowNumbers: false); } @@ -2553,13 +4778,13 @@ private void WriteMiscellaneousBlock() #line hidden #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\MiscellaneousBlock.ttinclude" -this.Write(" };\r\n }\r\n\r\n [DoesNotReturn]\r\n private static void ThrowArgumentNullException(string paramName)\r\n {\r\n throw new ArgumentNullException(paramName);\r\n }\r\n"); +this.Write(" };\r\n }\r\n"); #line default #line hidden - #line 45 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\MiscellaneousBlock.ttinclude" + #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\Factory\MiscellaneousBlock.ttinclude" } @@ -2567,7 +4792,7 @@ private void WriteMiscellaneousBlock() #line default #line hidden - #line 61 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" + #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumFactoryWriter.tt" public EnumFactoryWriter(StringBuilder builder) : base(builder) { @@ -2576,7 +4801,7 @@ public EnumFactoryWriter(StringBuilder builder) : base(builder) public override string GetFileName() => $"{Model.Namespace ?? "_"}.{Model.Name}Factory.g.cs"; protected override bool CanGenerateFor(EnumToGenerate model) => - (model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0; + (model.SelectedGenerators & (SelectedGenerators.MainGenerator | SelectedGenerators.JsonConverter)) != 0; #line default diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumFactoryWriter.tt b/gen/EnumUtilities.Generators/CodeWriters/EnumFactoryWriter.tt index e356372..07ce906 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumFactoryWriter.tt +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumFactoryWriter.tt @@ -3,12 +3,16 @@ <#@ import namespace="Models" #> <#@ import namespace="System.Text" #> <#@ import namespace="T4CodeWriter" #> +<#@ include file="$(ProjectDir)CodeWriters\Factory\TryParseInternal.ttinclude"#> <#@ include file="$(ProjectDir)CodeWriters\Factory\DefaultBlock.ttinclude"#> -<#@ include file="$(ProjectDir)CodeWriters\Factory\LegacyDefaultBlock.ttinclude"#> <#@ include file="$(ProjectDir)CodeWriters\Factory\EnumMemberBlock.ttinclude"#> <#@ include file="$(ProjectDir)CodeWriters\Factory\DescriptionBlock.ttinclude"#> <#@ include file="$(ProjectDir)CodeWriters\Factory\DisplayBlock.ttinclude"#> +<#@ include file="$(ProjectDir)CodeWriters\Factory\JsonBlock.ttinclude"#> <#@ include file="$(ProjectDir)CodeWriters\Factory\MiscellaneousBlock.ttinclude"#> +<# +#nullable enable +#> // #nullable enable @@ -21,42 +25,35 @@ using Raiqub.Generators.EnumUtilities.Parsers; #pragma warning disable CS1591 // publicly visible type or member must be documented <# - if (!string.IsNullOrEmpty(Model.Namespace)) - { - WriteLine($"namespace {Model.Namespace}"); - WriteLine("{"); - PushIndent(); - } + if (!string.IsNullOrEmpty(Model.Namespace)) + { + WriteLine($"namespace {Model.Namespace}"); + WriteLine("{"); + PushIndent(); + } #> [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("<#= CurrentAssemblyName.Name #>", "<#= Append($"{CurrentAssemblyName.Version}") #>")] <#= Model.IsPublic ? "public" : "internal" #> static partial class <#= Model.Name #>Factory { - private static readonly <#= Model.MetadataClassName #>.StringParser s_stringParser = <#= Model.MetadataClassName #>.StringParser.Instance; -<# - if (Model.HasSerializationValue) - { -#> - private static readonly <#= Model.MetadataClassName #>.SerializationStringParser s_serializationStringParser = <#= Model.MetadataClassName #>.SerializationStringParser.Instance; <# - } -#> - -<# - WriteDefaultBlock(); - WriteLegacyDefaultBlock(); - WriteEnumMemberBlock(); - WriteDescriptionBlock(); - WriteDisplayBlock(); - WriteMiscellaneousBlock(); + if ((Model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0) + { + WriteDefaultBlock(); + WriteEnumMemberBlock(); + WriteDescriptionBlock(); + WriteDisplayBlock(); + WriteMiscellaneousBlock(); + } + WriteJsonBlock(); #> } <# - if (!string.IsNullOrEmpty(Model.Namespace)) - { - PopIndent(); - WriteLine("}"); - } + if (!string.IsNullOrEmpty(Model.Namespace)) + { + PopIndent(); + WriteLine("}"); + } #> <#+ public EnumFactoryWriter(StringBuilder builder) : base(builder) @@ -66,5 +63,5 @@ using Raiqub.Generators.EnumUtilities.Parsers; public override string GetFileName() => $"{Model.Namespace ?? "_"}.{Model.Name}Factory.g.cs"; protected override bool CanGenerateFor(EnumToGenerate model) => - (model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0; + (model.SelectedGenerators & (SelectedGenerators.MainGenerator | SelectedGenerators.JsonConverter)) != 0; #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/DefaultBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/DefaultBlock.ttinclude index 01afe48..fdbaba3 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/DefaultBlock.ttinclude +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/DefaultBlock.ttinclude @@ -3,82 +3,36 @@ private void WriteDefaultBlock() { - if (!HasMainGenerator) - return; -#> - /// Provides constant values for members names. - public static partial class Name - { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. - public const int MaxCharsLength = <#= Model.Values.Max(x => x.MemberName.Length) #>; -<#+ - foreach (var curr in Model.Values) + if (HasMainGenerator) { -#> - - /// The string representation of name. - public const string <#= curr.MemberName #> = "<#= curr.MemberName #>"; -<#+ + WriteNames( + "Name", + "members names", + "name", + "converting", + x => x.MemberName); } -#> - } - - /// Provides static values for UTF-8 encoded members names. - public static partial class Utf8Name - { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. - public const int MaxBytesLength = <#= Model.Values.Max(x => _utf8Encoding.GetByteCount(x.MemberName)) #>; -<#+ - foreach (var curr in Model.Values) - { -#> - /// The UTF-8 representation of name. - public static ReadOnlySpan <#= curr.MemberName #> => new byte[<#= _utf8Encoding.GetByteCount(curr.MemberName) #>] { <#= _utf8Encoding.GetBytes(curr.MemberName).JoinToString() #> }; -<#+ - } -#> - } -<#+ if (HasMainGenerator && Model.HasSerializationValue) { -#> - - /// Provides constant values for serialized members values. - public static partial class SerializedValue - { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. - public const int MaxCharsLength = <#= Model.Values.Max(x => x.ResolvedSerializedValue.Length) #>; -<#+ - foreach (var curr in Model.Values) - { -#> - - /// The string representation of serialized value. - public const string <#= curr.MemberName #> = "<#= curr.ResolvedSerializedValue #>"; -<#+ + WriteLine(); + WriteNames( + "SerializedValue", + "serialized members values", + "serialized value", + "serializing", + x => x.ResolvedSerializedValue); } -#> - } - /// Provides static values for UTF-8 encoded members serialized values. - public static partial class Utf8SerializedValue - { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. - public const int MaxBytesLength = <#= Model.Values.Max(x => _utf8Encoding.GetByteCount(x.ResolvedSerializedValue)) #>; -<#+ - foreach (var curr in Model.Values) + if (HasMainGenerator && Model.HasJsonProperty) { -#> - - /// The UTF-8 representation of serialized value. - public static ReadOnlySpan <#= curr.MemberName #> => new byte[<#= _utf8Encoding.GetByteCount(curr.ResolvedSerializedValue) #>] { <#= _utf8Encoding.GetBytes(curr.ResolvedSerializedValue).JoinToString() #> }; -<#+ - } -#> - } -<#+ + WriteLine(); + WriteNames( + "JsonValue", + "serialized members values", + "serialized value", + "serializing", + x => x.ResolvedJsonValue); } - WriteLine(); } #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/ExtensionsBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/ExtensionsBlock.ttinclude deleted file mode 100644 index b8b2517..0000000 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/ExtensionsBlock.ttinclude +++ /dev/null @@ -1,336 +0,0 @@ -<#+ - private void WriteExtensionsBlock() - { -#> - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnum<#= Model.IsFlags ? "Flags" : "" #>Formatter<<#= Model.UnderlyingType #>> - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(<#= Model.UnderlyingType #> value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(<#= Model.UnderlyingType #> value) => value.ToString(); -<#+ - if (Model.IsFlags) - { -#> - - /// - public int? TryGetStringLengthForMember(<#= Model.UnderlyingType #> value) - { - if (value == 0) - { - return <#= - Model.Values.FirstOrDefault(x => x.MemberValue == "0")?.MemberName.Length ?? 1 #>; - } - - int count = 0, foundItemsCount = 0; -<#+ - foreach ( - var curr in - Model.UniqueValues.OrderByDescending(x => x.RealMemberValue).Where(x => x.MemberValue != "0")) - { -#> - if ((value & <#= curr.MemberValue #>) == <#= curr.MemberValue #>) - { - value -= <#= curr.MemberValue #>; - count = checked(count + <#= curr.MemberName.Length #>); - foundItemsCount++; - } -<#+ - } -#> - - if (value != 0) - { - return null; - } - - const int separatorStringLength = 2; - return checked(count + (separatorStringLength * (foundItemsCount - 1))); - } - - /// - public string? TryGetStringForMember(<#= Model.UnderlyingType #> value) - { - if (value == 0) - { - return "<#= Model.Values.FirstOrDefault(x => x.MemberValue == "0")?.MemberName ?? "0" #>"; - } - - Span<<#= Model.UnderlyingType #>> foundItems = stackalloc <#= Model.UnderlyingType #>[<#= GetMappedBitCount() #>]; - int count = 0, foundItemsCount = 0; -<#+ - foreach ( - var curr in - Model.UniqueValues.OrderByDescending(x => x.RealMemberValue).Where(x => x.MemberValue != "0")) - { -#> - if ((value & <#= curr.MemberValue #>) == <#= curr.MemberValue #>) - { - value -= <#= curr.MemberValue #>; - count = checked(count + <#= curr.MemberName.Length #>); - foundItems[foundItemsCount++] = <#= curr.MemberValue #>; - } -<#+ - } -#> - - if (value != 0) - { - return null; - } - - if (foundItemsCount == 1) - { - return GetStringForSingleMember(foundItems[0]); - } - - return EnumStringFormatter.WriteMultipleFoundFlagsNames(this, count, foundItemsCount, foundItems); - } - - public string GetStringForSingleMember(<#= Model.UnderlyingType #> value) - { - return value switch - { -<#+ - foreach (var curr in Model.UniqueValues) - { -#> - <#= curr.MemberValue #> => "<#= curr.MemberName #>", -<#+ - } -#> - _ => throw new ArgumentOutOfRangeException() - }; - } -<#+ - } - else - { -#> - - /// - public int? TryGetStringLengthForMember(<#= Model.UnderlyingType #> value) - { - return value switch - { -<#+ - foreach (var curr in Model.UniqueValues) - { -#> - <#= curr.MemberValue #> => <#= curr.MemberName.Length #>, -<#+ - } -#> - _ => null - }; - } - - /// - public string? TryGetStringForMember(<#= Model.UnderlyingType #> value) - { - return value switch - { -<#+ - foreach (var curr in Model.UniqueValues) - { -#> - <#= curr.MemberValue #> => "<#= curr.MemberName #>", -<#+ - } -#> - _ => null - }; - } -<#+ - } -#> - } -<#+ - if (HasMainGenerator && Model.HasSerializationValue) - { -#> - - /// Provides support for formatting serialized values. - internal sealed partial class SerializationStringFormatter : IEnum<#= Model.IsFlags ? "Flags" : "" #>Formatter<<#= Model.UnderlyingType #>> - { - /// Gets the singleton instance of the class. - public static SerializationStringFormatter Instance = new SerializationStringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(<#= Model.UnderlyingType #> value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(<#= Model.UnderlyingType #> value) => value.ToString(); -<#+ - if (Model.IsFlags) - { -#> - - /// - public int? TryGetStringLengthForMember(<#= Model.UnderlyingType #> value) - { - if (value == 0) - { - return <#= - Model.Values.FirstOrDefault(x => x.MemberValue == "0")?.ResolvedSerializedValue.Length ?? 1 #>; - } - - int count = 0, foundItemsCount = 0; -<#+ - foreach ( - var curr in - Model.UniqueValues.OrderByDescending(x => x.RealMemberValue).Where(x => x.MemberValue != "0")) - { -#> - if ((value & <#= curr.MemberValue #>) == <#= curr.MemberValue #>) - { - value -= <#= curr.MemberValue #>; - count = checked(count + <#= curr.ResolvedSerializedValue.Length #>); - foundItemsCount++; - } -<#+ - } -#> - - if (value != 0) - { - return null; - } - - const int separatorStringLength = 2; - return checked(count + (separatorStringLength * (foundItemsCount - 1))); - } - - /// - public string? TryGetStringForMember(<#= Model.UnderlyingType #> value) - { - if (value == 0) - { - return "<#= - Model.Values.FirstOrDefault(x => x.MemberValue == "0")?.ResolvedSerializedValue ?? "0" #>"; - } - - Span<<#= Model.UnderlyingType #>> foundItems = stackalloc <#= Model.UnderlyingType #>[<#= GetMappedBitCount() #>]; - int count = 0, foundItemsCount = 0; -<#+ - foreach ( - var curr in - Model.UniqueValues.OrderByDescending(x => x.RealMemberValue).Where(x => x.MemberValue != "0")) - { -#> - if ((value & <#= curr.MemberValue #>) == <#= curr.MemberValue #>) - { - value -= <#= curr.MemberValue #>; - count = checked(count + <#= curr.ResolvedSerializedValue.Length #>); - foundItems[foundItemsCount++] = <#= curr.MemberValue #>; - } -<#+ - } -#> - - if (value != 0) - { - return null; - } - - if (foundItemsCount == 1) - { - return GetStringForSingleMember(foundItems[0]); - } - - return EnumStringFormatter.WriteMultipleFoundFlagsNames(this, count, foundItemsCount, foundItems); - } - - public string GetStringForSingleMember(<#= Model.UnderlyingType #> value) - { - return value switch - { -<#+ - foreach (var curr in Model.UniqueValues) - { -#> - <#= curr.MemberValue #> => "<#= curr.ResolvedSerializedValue #>", -<#+ - } -#> - _ => throw new ArgumentOutOfRangeException() - }; - } -<#+ - } - else - { -#> - - /// - public int? TryGetStringLengthForMember(<#= Model.UnderlyingType #> value) - { - return value switch - { -<#+ - foreach (var curr in Model.UniqueValues) - { -#> - <#= curr.MemberValue #> => <#= curr.ResolvedSerializedValue.Length #>, -<#+ - } -#> - _ => null - }; - } - - /// - public string? TryGetStringForMember(<#= Model.UnderlyingType #> value) - { - return value switch - { -<#+ - foreach (var curr in Model.UniqueValues) - { -#> - <#= curr.MemberValue #> => "<#= curr.ResolvedSerializedValue #>", -<#+ - } -#> - _ => null - }; - } -<#+ - } -#> - } -<#+ - } - } - - private int GetBitCount() => Model.UnderlyingType switch { - "byte" => 8, - "sbyte" => 8, - "short" => 16, - "ushort" => 16, - "int" => 32, - "uint" => 32, - "long" => 64, - "ulong" => 64, - _ => 64, - }; - - private int GetMappedBitCount() - { - if (Model.Values.Any(x => x.MemberValue[0] == '-')) - return GetBitCount(); - - return GetBitCount() - - (BitOperations.LeadingZeroCount(Model.Values.Select(x => Convert.ToUInt64(x.RealMemberValue)).Max()) - - (64 - GetBitCount())); - } -#> diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/FactoryBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/FactoryBlock.ttinclude deleted file mode 100644 index 4823014..0000000 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/FactoryBlock.ttinclude +++ /dev/null @@ -1,208 +0,0 @@ -<#+ - private void WriteFactoryBlock() - { - bool enableDescription = HasMainGenerator && Model.HasDescription; -#> - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser<<#= Model.UnderlyingType #>><#= - enableDescription ? Append($", IEnumDescriptionParser<{Model.UnderlyingType}>") : new None() #> - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public <#= Model.UnderlyingType #> BitwiseOr(<#= Model.UnderlyingType #> value1, <#= Model.UnderlyingType #> value2) => unchecked((<#= Model.UnderlyingType #>)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out <#= Model.UnderlyingType #> result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out <#= Model.UnderlyingType #> result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - -<#+ - var lookupTable = Model.Values.ToLookup(x => x.MemberName[0]); -#> - switch (value[0]) - { -<#+ - foreach (var curr in lookupTable) - { - if (char.ToUpperInvariant(curr.Key) == curr.Key && char.ToLowerInvariant(curr.Key) == curr.Key) - { -#> - case '<#= curr.Key #>': -<#+ - } - else - { -#> - case '<#= char.ToUpperInvariant(curr.Key) #>': - case '<#= char.ToLowerInvariant(curr.Key) #>': -<#+ - } -#> - switch (value) - { -<#+ - foreach (var enumValue in curr) - { -#> - case { } when value.Equals("<#= enumValue.MemberName #>", comparisonType): - result = <#= enumValue.MemberValue #>; - return true; -<#+ - } -#> - } - goto default; -<#+ - } -#> - default: - result = 0; - return false; - } - } -<#+ - if (enableDescription) - { -#> - - /// - public bool TryParseDescription(ReadOnlySpan value, StringComparison comparisonType, out <#= Model.UnderlyingType #> result) - { -<#+ - if (Model.Values.All(x => x.Description == null)) - { -#> - result = default; - return false; -<#+ - } - else - { -#> - switch (value) - { -<#+ - foreach (var curr in Model.Values.Where(x => x.Description != null)) - { -#> - case { } s when s.Equals("<#= curr.Description #>", comparisonType): - result = <#= curr.MemberValue #>; - return true; -<#+ - } -#> - default: - result = default; - return false; - } -<#+ - } -#> - } -<#+ - } -#> - } -<#+ - if (HasMainGenerator && Model.HasSerializationValue) - { -#> - - /// Provides support for parsing serialized values. - internal sealed partial class SerializationStringParser : IEnumParser<<#= Model.UnderlyingType #>> - { - /// Gets the singleton instance of the class. - public static SerializationStringParser Instance = new SerializationStringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public <#= Model.UnderlyingType #> BitwiseOr(<#= Model.UnderlyingType #> value1, <#= Model.UnderlyingType #> value2) => unchecked((<#= Model.UnderlyingType #>)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out <#= Model.UnderlyingType #> result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out <#= Model.UnderlyingType #> result) - { - if (value.IsEmpty) - { -<#+ - var binEmptyValue = Model.Values.FirstOrDefault(x => x.ResolvedSerializedValue.Length == 0); - if (binEmptyValue != null) - { -#> - result = <#= binEmptyValue.MemberValue #>; - return true; -<#+ - } - else - { -#> - result = 0; - return false; -<#+ - } -#> - } - -<#+ - var binLookupTable = Model.Values.ToLookup(x => x.ResolvedSerializedValue[0]); -#> - switch (value[0]) - { -<#+ - foreach (var curr in binLookupTable) - { - if (char.ToUpperInvariant(curr.Key) == curr.Key && char.ToLowerInvariant(curr.Key) == curr.Key) - { -#> - case '<#= curr.Key #>': -<#+ - } - else - { -#> - case '<#= char.ToUpperInvariant(curr.Key) #>': - case '<#= char.ToLowerInvariant(curr.Key) #>': -<#+ - } -#> - switch (value) - { -<#+ - foreach (var enumValue in curr) - { -#> - case { } when value.Equals("<#= enumValue.ResolvedSerializedValue #>", comparisonType): - result = <#= enumValue.MemberValue #>; - return true; -<#+ - } -#> - } - goto default; -<#+ - } -#> - default: - result = 0; - return false; - } - } - } -<#+ - } - } -#> diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/NamesInternal.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/NamesInternal.ttinclude new file mode 100644 index 0000000..ab5507d --- /dev/null +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumInfo/NamesInternal.ttinclude @@ -0,0 +1,45 @@ +<#+ + private void WriteNames( + string className, + string xmlDocAllRef, + string xmlDocItemRef, + string xmlDocAction, + Func keySelector) + { +#> + /// Provides constant values for <#= xmlDocAllRef #>. + public static partial class <#= className #> + { + /// Represents the largest possible number of characters produced by <#= xmlDocAction #> a value to string, based on defined members. + public const int MaxCharsLength = <#= Model.Values.Max(x => keySelector(x).Length) #>; +<#+ + foreach (var curr in Model.Values) + { +#> + + /// The string representation of <#= xmlDocItemRef #>. + public const string <#= curr.MemberName #> = "<#= keySelector(curr) #>"; +<#+ + } +#> + } + + /// Provides static values for UTF-8 encoded <#= xmlDocAllRef #>. + public static partial class Utf8<#= className #> + { + /// Represents the largest possible number of bytes produced by <#= xmlDocAction #> a value to UTF-8 string, based on defined members. + public const int MaxBytesLength = <#= Model.Values.Max(x => _utf8Encoding.GetByteCount(keySelector(x))) #>; +<#+ + foreach (var curr in Model.Values) + { +#> + + /// The UTF-8 representation of <#= xmlDocItemRef #>. + public static ReadOnlySpan <#= curr.MemberName #> => new byte[<#= _utf8Encoding.GetByteCount(keySelector(curr)) #>] { <#= _utf8Encoding.GetBytes(keySelector(curr)).JoinToString() #> }; +<#+ + } +#> + } +<#+ + } +#> diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumInfoWriter.cs b/gen/EnumUtilities.Generators/CodeWriters/EnumInfoWriter.cs index 57def67..a59c77b 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumInfoWriter.cs +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumInfoWriter.cs @@ -29,23 +29,29 @@ public partial class EnumInfoWriter : CodeWriterBase /// public override string TransformText() { - this.Write("\r\n"); this.Write("\r\n"); this.Write("\r\n// \r\n#nullable enable\r\n\r\nusing System;\r\nusing System.Runtime.CompilerServices;\r\nusing Raiqub.Generators.EnumUtilities.Formatters;\r\nusing Raiqub.Generators.EnumUtilities.Parsers;\r\n\r\n#pragma warning disable CS1591 // publicly visible type or member must be documented\r\n\r\n"); - #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfoWriter.tt" + #line 18 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfoWriter.tt" - if (!string.IsNullOrEmpty(Model.Namespace)) - { - WriteLine($"namespace {Model.Namespace}"); - WriteLine("{"); - PushIndent(); - } + if (!string.IsNullOrEmpty(Model.Namespace)) + { + WriteLine($"namespace {Model.Namespace}"); + WriteLine("{"); + PushIndent(); + } #line default #line hidden - this.Write("[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]\r\n[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\""); + this.Write("/// Provides metadata for \r\n[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]\r\n[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\""); #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfoWriter.tt" this.Write(this.ToStringHelper.ToStringWithCulture(CurrentAssemblyName.Name)); @@ -77,22 +83,20 @@ public override string TransformText() #line 31 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfoWriter.tt" - WriteDefaultBlock(); - WriteExtensionsBlock(); - WriteFactoryBlock(); + WriteDefaultBlock(); #line default #line hidden this.Write("}\r\n"); - #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfoWriter.tt" + #line 35 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfoWriter.tt" - if (!string.IsNullOrEmpty(Model.Namespace)) - { - PopIndent(); - WriteLine("}"); - } + if (!string.IsNullOrEmpty(Model.Namespace)) + { + PopIndent(); + WriteLine("}"); + } #line default @@ -100,198 +104,112 @@ public override string TransformText() return this.GenerationEnvironment.ToString(); } - #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" - - private static readonly Encoding _utf8Encoding = Encoding.UTF8; + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" - private void WriteDefaultBlock() + private void WriteNames( + string className, + string xmlDocAllRef, + string xmlDocItemRef, + string xmlDocAction, + Func keySelector) { - if (!HasMainGenerator) - return; #line default #line hidden - #line 9 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" this.Write(" /// Provides constant values for \r\n public static partial class Name\r\n {\r\n /// Represents the largest possible number of characters produced by converting an \r\n public const int MaxCharsLength = "); - - - #line default - #line hidden - - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.Max(x => x.MemberName.Length))); - - - #line default - #line hidden - - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(";\r\n"); - - - #line default - #line hidden - - #line 14 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" - - foreach (var curr in Model.Values) - { - - - #line default - #line hidden - - #line 19 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("\r\n /// The string representation of \r\n public const string "); - - - #line default - #line hidden - - #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName)); - - - #line default - #line hidden - - #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(" = \""); + #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write("\" /> "); #line default #line hidden - #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName)); + #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(xmlDocAllRef)); #line default #line hidden - #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("\";\r\n"); + #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(".\r\n public static partial class "); #line default #line hidden - #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" - - } + #line 11 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(className)); #line default #line hidden - #line 24 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(" }\r\n\r\n /// Provides static values for Represents the largest possible number of characters produced by "); #line default #line hidden - #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(xmlDocAction)); #line default #line hidden - #line 26 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("\" /> UTF-8 encoded members names.\r\n public static partial class Utf8Name\r\n {\r\n /// Represents the largest possible number of bytes produced by converting an \r\n public const int MaxBytesLength = "); + #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write("\" /> value to string, based on defined members.\r\n public const int MaxCharsLength = "); #line default #line hidden - #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.Max(x => _utf8Encoding.GetByteCount(x.MemberName)))); + #line 14 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.Max(x => keySelector(x).Length))); #line default #line hidden - #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 14 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" this.Write(";\r\n"); #line default #line hidden - #line 31 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 15 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" foreach (var curr in Model.Values) { @@ -300,84 +218,84 @@ private void WriteDefaultBlock() #line default #line hidden - #line 36 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("\r\n /// The UTF-8 representation of The string representation of \r\n public static ReadOnlySpan "); + #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write("\" /> "); #line default #line hidden - #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName)); + #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(xmlDocItemRef)); #line default #line hidden - #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(" => new byte["); + #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(".\r\n public const string "); #line default #line hidden - #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(_utf8Encoding.GetByteCount(curr.MemberName))); + #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName)); #line default #line hidden - #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("] { "); + #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(" = \""); #line default #line hidden - #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(_utf8Encoding.GetBytes(curr.MemberName).JoinToString())); + #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(keySelector(curr))); #line default #line hidden - #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(" };\r\n"); + #line 21 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write("\";\r\n"); #line default #line hidden - #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 22 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" } @@ -385,287 +303,198 @@ private void WriteDefaultBlock() #line default #line hidden - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(" }\r\n"); - - - #line default - #line hidden - - #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" - - if (HasMainGenerator && Model.HasSerializationValue) - { - - - #line default - #line hidden - - #line 47 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("\r\n /// Provides constant values for Provides static values for \r\n public static partial class SerializedValue\r\n {\r\n /// Represents the largest possible number of characters produced by converting an UTF-8 encoded "); #line default #line hidden - #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); + #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(xmlDocAllRef)); #line default #line hidden - #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("\" /> value to string, based on defined members. This field is constant.\r\n public const int MaxCharsLength = "); + #line 27 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(".\r\n public static partial class Utf8"); #line default #line hidden - #line 51 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.Max(x => x.ResolvedSerializedValue.Length))); + #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(className)); #line default #line hidden - #line 51 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(";\r\n"); + #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write("\r\n {\r\n /// Represents the largest possible number of bytes produced by "); #line default #line hidden - #line 52 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" - - foreach (var curr in Model.Values) - { + #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(xmlDocAction)); #line default #line hidden - #line 57 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("\r\n /// The string representation of serialized \r\n public const string "); - - - #line default - #line hidden - - #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName)); - - - #line default - #line hidden - - #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(" = \""); - - - #line default - #line hidden - - #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.ResolvedSerializedValue)); + #line 30 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write("\" /> value to UTF-8 string, based on defined members.\r\n public const int MaxBytesLength = "); #line default #line hidden - #line 58 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("\";\r\n"); + #line 31 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.Max(x => _utf8Encoding.GetByteCount(keySelector(x))))); #line default #line hidden - #line 59 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" - - } + #line 31 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(";\r\n"); #line default #line hidden - #line 62 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(" }\r\n\r\n /// Provides static values for \r\n public static partial class Utf8SerializedValue\r\n {\r\n /// Represents the largest possible number of bytes produced by converting an The UTF-8 representation of \r\n public const int MaxBytesLength = "); - - - #line default - #line hidden - - #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.Max(x => _utf8Encoding.GetByteCount(x.ResolvedSerializedValue)))); - - - #line default - #line hidden - - #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(";\r\n"); - - - #line default - #line hidden - - #line 69 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" - - foreach (var curr in Model.Values) - { - - - #line default - #line hidden - - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write("\r\n /// The UTF-8 representation of serialized \r\n public static ReadOnlySpan "); + #line 37 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(".\r\n public static ReadOnlySpan "); #line default #line hidden - #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName)); #line default #line hidden - #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" this.Write(" => new byte["); #line default #line hidden - #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(_utf8Encoding.GetByteCount(curr.ResolvedSerializedValue))); + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(_utf8Encoding.GetByteCount(keySelector(curr)))); #line default #line hidden - #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" this.Write("] { "); #line default #line hidden - #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(_utf8Encoding.GetBytes(curr.ResolvedSerializedValue).JoinToString())); + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" +this.Write(this.ToStringHelper.ToStringWithCulture(_utf8Encoding.GetBytes(keySelector(curr)).JoinToString())); #line default #line hidden - #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 38 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" this.Write(" };\r\n"); #line default #line hidden - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" } @@ -673,2190 +502,57 @@ private void WriteDefaultBlock() #line default #line hidden - #line 79 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" this.Write(" }\r\n"); #line default #line hidden - #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" + #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\NamesInternal.ttinclude" - } - WriteLine(); } #line default #line hidden - #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - private void WriteExtensionsBlock() - { - - - #line default - #line hidden - - #line 5 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" /// Provides support for formatting \r\n internal sealed partial class StringFormatter : IEnum"); - - - #line default - #line hidden - - #line 6 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsFlags ? "Flags" : "")); - - - #line default - #line hidden - - #line 6 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("Formatter<"); - - - #line default - #line hidden - - #line 6 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 6 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(">\r\n {\r\n /// Gets the singleton instance of the class.\r\n public static StringFormatter Instance = new StringFormatter();\r\n\r\n /// \r\n [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n public int GetStringLengthForNumber("); - - - #line default - #line hidden - - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\DefaultBlock.ttinclude" - - #line default - #line hidden - - #line 13 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value) => EnumNumericFormatter.GetStringLength(value);\r\n\r\n /// \r\n [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n public string GetStringForNumber("); + private static readonly Encoding _utf8Encoding = Encoding.UTF8; - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + private void WriteDefaultBlock() + { + if (HasMainGenerator) + { + WriteNames( + "Name", + "members names", + "name", + "converting", + x => x.MemberName); + } - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value) => value.ToString();\r\n"); + if (HasMainGenerator && Model.HasSerializationValue) + { + WriteLine(); + WriteNames( + "SerializedValue", + "serialized members values", + "serialized value", + "serializing", + x => x.ResolvedSerializedValue); + } - - #line default - #line hidden - - #line 18 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - if (Model.IsFlags) - { - - - #line default - #line hidden - - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\r\n /// \r\n public int? TryGetStringLengthForMember("); - - - #line default - #line hidden - - #line 24 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 24 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n if (value == 0)\r\n {\r\n return "); - - - #line default - #line hidden - - #line 28 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.FirstOrDefault(x => x.MemberValue == "0")?.MemberName.Length ?? 1)); - - - #line default - #line hidden - - #line 29 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(";\r\n }\r\n\r\n int count = 0, foundItemsCount = 0;\r\n"); - - - #line default - #line hidden - - #line 33 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach ( - var curr in - Model.UniqueValues.OrderByDescending(x => x.RealMemberValue).Where(x => x.MemberValue != "0")) - { - - - #line default - #line hidden - - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" if ((value & "); - - - #line default - #line hidden - - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(") == "); - - - #line default - #line hidden - - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 39 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(")\r\n {\r\n value -= "); - - - #line default - #line hidden - - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 41 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(";\r\n count = checked(count + "); - - - #line default - #line hidden - - #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName.Length)); - - - #line default - #line hidden - - #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(");\r\n foundItemsCount++;\r\n }\r\n"); - - - #line default - #line hidden - - #line 45 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\r\n if (value != 0)\r\n {\r\n return null;\r\n }\r\n\r\n const int separatorStringLength = 2;\r\n return checked(count + (separatorStringLength * (foundItemsCount - 1)));\r\n }\r\n\r\n /// \r\n public string? TryGetStringForMember("); - - - #line default - #line hidden - - #line 59 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 59 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n if (value == 0)\r\n {\r\n return \""); - - - #line default - #line hidden - - #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.FirstOrDefault(x => x.MemberValue == "0")?.MemberName ?? "0")); - - - #line default - #line hidden - - #line 63 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\";\r\n }\r\n\r\n Span<"); - - - #line default - #line hidden - - #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("> foundItems = stackalloc "); - - - #line default - #line hidden - - #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("["); - - - #line default - #line hidden - - #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(GetMappedBitCount())); - - - #line default - #line hidden - - #line 66 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("];\r\n int count = 0, foundItemsCount = 0;\r\n"); - - - #line default - #line hidden - - #line 68 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach ( - var curr in - Model.UniqueValues.OrderByDescending(x => x.RealMemberValue).Where(x => x.MemberValue != "0")) - { - - - #line default - #line hidden - - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" if ((value & "); - - - #line default - #line hidden - - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(") == "); - - - #line default - #line hidden - - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 74 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(")\r\n {\r\n value -= "); - - - #line default - #line hidden - - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 76 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(";\r\n count = checked(count + "); - - - #line default - #line hidden - - #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName.Length)); - - - #line default - #line hidden - - #line 77 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(");\r\n foundItems[foundItemsCount++] = "); - - - #line default - #line hidden - - #line 78 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 78 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(";\r\n }\r\n"); - - - #line default - #line hidden - - #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 84 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\r\n if (value != 0)\r\n {\r\n return null;\r\n }\r\n\r\n if (foundItemsCount == 1)\r\n {\r\n return GetStringForSingleMember(foundItems[0]);\r\n }\r\n\r\n return EnumStringFormatter.WriteMultipleFoundFlagsNames(this, count, foundItemsCount, foundItems);\r\n }\r\n\r\n public string GetStringForSingleMember("); - - - #line default - #line hidden - - #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 97 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n return value switch\r\n {\r\n"); - - - #line default - #line hidden - - #line 101 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach (var curr in Model.UniqueValues) - { - - - #line default - #line hidden - - #line 105 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" "); - - - #line default - #line hidden - - #line 105 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 105 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" => \""); - - - #line default - #line hidden - - #line 105 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName)); - - - #line default - #line hidden - - #line 105 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\",\r\n"); - - - #line default - #line hidden - - #line 106 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 109 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" _ => throw new ArgumentOutOfRangeException()\r\n };\r\n }\r\n"); - - - #line default - #line hidden - - #line 112 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - else - { - - - #line default - #line hidden - - #line 118 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\r\n /// \r\n public int? TryGetStringLengthForMember("); - - - #line default - #line hidden - - #line 119 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 119 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n return value switch\r\n {\r\n"); - - - #line default - #line hidden - - #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach (var curr in Model.UniqueValues) - { - - - #line default - #line hidden - - #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" "); - - - #line default - #line hidden - - #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" => "); - - - #line default - #line hidden - - #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName.Length)); - - - #line default - #line hidden - - #line 127 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(",\r\n"); - - - #line default - #line hidden - - #line 128 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 131 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" _ => null\r\n };\r\n }\r\n\r\n /// \r\n public string? TryGetStringForMember("); - - - #line default - #line hidden - - #line 136 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 136 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n return value switch\r\n {\r\n"); - - - #line default - #line hidden - - #line 140 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach (var curr in Model.UniqueValues) - { - - - #line default - #line hidden - - #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" "); - - - #line default - #line hidden - - #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" => \""); - - - #line default - #line hidden - - #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberName)); - - - #line default - #line hidden - - #line 144 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\",\r\n"); - - - #line default - #line hidden - - #line 145 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 148 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" _ => null\r\n };\r\n }\r\n"); - - - #line default - #line hidden - - #line 151 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 154 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" }\r\n"); - - - #line default - #line hidden - - #line 155 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - if (HasMainGenerator && Model.HasSerializationValue) - { - - - #line default - #line hidden - - #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\r\n /// Provides support for formatting \r\n internal sealed partial class SerializationStringFormatter : IEnum"); - - - #line default - #line hidden - - #line 161 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.IsFlags ? "Flags" : "")); - - - #line default - #line hidden - - #line 161 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("Formatter<"); - - - #line default - #line hidden - - #line 161 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 161 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(">\r\n {\r\n /// Gets the singleton instance of the class.\r\n public static SerializationStringFormatter Instance = new SerializationStringFormatter();\r\n\r\n /// \r\n [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n public int GetStringLengthForNumber("); - - - #line default - #line hidden - - #line 168 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 168 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value) => EnumNumericFormatter.GetStringLength(value);\r\n\r\n /// \r\n [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n public string GetStringForNumber("); - - - #line default - #line hidden - - #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value) => value.ToString();\r\n"); - - - #line default - #line hidden - - #line 173 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - if (Model.IsFlags) - { - - - #line default - #line hidden - - #line 178 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\r\n /// \r\n public int? TryGetStringLengthForMember("); - - - #line default - #line hidden - - #line 179 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 179 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n if (value == 0)\r\n {\r\n return "); - - - #line default - #line hidden - - #line 183 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.FirstOrDefault(x => x.MemberValue == "0")?.ResolvedSerializedValue.Length ?? 1)); - - - #line default - #line hidden - - #line 184 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(";\r\n }\r\n\r\n int count = 0, foundItemsCount = 0;\r\n"); - - - #line default - #line hidden - - #line 188 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach ( - var curr in - Model.UniqueValues.OrderByDescending(x => x.RealMemberValue).Where(x => x.MemberValue != "0")) - { - - - #line default - #line hidden - - #line 194 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" if ((value & "); - - - #line default - #line hidden - - #line 194 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 194 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(") == "); - - - #line default - #line hidden - - #line 194 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 194 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(")\r\n {\r\n value -= "); - - - #line default - #line hidden - - #line 196 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 196 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(";\r\n count = checked(count + "); - - - #line default - #line hidden - - #line 197 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.ResolvedSerializedValue.Length)); - - - #line default - #line hidden - - #line 197 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(");\r\n foundItemsCount++;\r\n }\r\n"); - - - #line default - #line hidden - - #line 200 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 204 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\r\n if (value != 0)\r\n {\r\n return null;\r\n }\r\n\r\n const int separatorStringLength = 2;\r\n return checked(count + (separatorStringLength * (foundItemsCount - 1)));\r\n }\r\n\r\n /// \r\n public string? TryGetStringForMember("); - - - #line default - #line hidden - - #line 214 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 214 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n if (value == 0)\r\n {\r\n return \""); - - - #line default - #line hidden - - #line 218 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.FirstOrDefault(x => x.MemberValue == "0")?.ResolvedSerializedValue ?? "0")); - - - #line default - #line hidden - - #line 219 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\";\r\n }\r\n\r\n Span<"); - - - #line default - #line hidden - - #line 222 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 222 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("> foundItems = stackalloc "); - - - #line default - #line hidden - - #line 222 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 222 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("["); - - - #line default - #line hidden - - #line 222 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(GetMappedBitCount())); - - - #line default - #line hidden - - #line 222 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("];\r\n int count = 0, foundItemsCount = 0;\r\n"); - - - #line default - #line hidden - - #line 224 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach ( - var curr in - Model.UniqueValues.OrderByDescending(x => x.RealMemberValue).Where(x => x.MemberValue != "0")) - { - - - #line default - #line hidden - - #line 230 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" if ((value & "); - - - #line default - #line hidden - - #line 230 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 230 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(") == "); - - - #line default - #line hidden - - #line 230 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 230 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(")\r\n {\r\n value -= "); - - - #line default - #line hidden - - #line 232 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 232 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(";\r\n count = checked(count + "); - - - #line default - #line hidden - - #line 233 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.ResolvedSerializedValue.Length)); - - - #line default - #line hidden - - #line 233 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(");\r\n foundItems[foundItemsCount++] = "); - - - #line default - #line hidden - - #line 234 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 234 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(";\r\n }\r\n"); - - - #line default - #line hidden - - #line 236 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 240 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\r\n if (value != 0)\r\n {\r\n return null;\r\n }\r\n\r\n if (foundItemsCount == 1)\r\n {\r\n return GetStringForSingleMember(foundItems[0]);\r\n }\r\n\r\n return EnumStringFormatter.WriteMultipleFoundFlagsNames(this, count, foundItemsCount, foundItems);\r\n }\r\n\r\n public string GetStringForSingleMember("); - - - #line default - #line hidden - - #line 253 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 253 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n return value switch\r\n {\r\n"); - - - #line default - #line hidden - - #line 257 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach (var curr in Model.UniqueValues) - { - - - #line default - #line hidden - - #line 261 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" "); - - - #line default - #line hidden - - #line 261 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 261 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" => \""); - - - #line default - #line hidden - - #line 261 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.ResolvedSerializedValue)); - - - #line default - #line hidden - - #line 261 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\",\r\n"); - - - #line default - #line hidden - - #line 262 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 265 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" _ => throw new ArgumentOutOfRangeException()\r\n };\r\n }\r\n"); - - - #line default - #line hidden - - #line 268 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - else - { - - - #line default - #line hidden - - #line 274 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\r\n /// \r\n public int? TryGetStringLengthForMember("); - - - #line default - #line hidden - - #line 275 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 275 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n return value switch\r\n {\r\n"); - - - #line default - #line hidden - - #line 279 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach (var curr in Model.UniqueValues) - { - - - #line default - #line hidden - - #line 283 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" "); - - - #line default - #line hidden - - #line 283 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 283 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" => "); - - - #line default - #line hidden - - #line 283 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.ResolvedSerializedValue.Length)); - - - #line default - #line hidden - - #line 283 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(",\r\n"); - - - #line default - #line hidden - - #line 284 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 287 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" _ => null\r\n };\r\n }\r\n\r\n /// \r\n public string? TryGetStringForMember("); - - - #line default - #line hidden - - #line 292 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 292 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" value)\r\n {\r\n return value switch\r\n {\r\n"); - - - #line default - #line hidden - - #line 296 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - foreach (var curr in Model.UniqueValues) - { - - - #line default - #line hidden - - #line 300 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" "); - - - #line default - #line hidden - - #line 300 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 300 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" => \""); - - - #line default - #line hidden - - #line 300 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.ResolvedSerializedValue)); - - - #line default - #line hidden - - #line 300 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write("\",\r\n"); - - - #line default - #line hidden - - #line 301 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 304 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" _ => null\r\n };\r\n }\r\n"); - - - #line default - #line hidden - - #line 307 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 310 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" -this.Write(" }\r\n"); - - - #line default - #line hidden - - #line 311 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" - - } - } - - private int GetBitCount() => Model.UnderlyingType switch { - "byte" => 8, - "sbyte" => 8, - "short" => 16, - "ushort" => 16, - "int" => 32, - "uint" => 32, - "long" => 64, - "ulong" => 64, - _ => 64, - }; - - private int GetMappedBitCount() - { - if (Model.Values.Any(x => x.MemberValue[0] == '-')) - return GetBitCount(); - - return GetBitCount() - - (BitOperations.LeadingZeroCount(Model.Values.Select(x => Convert.ToUInt64(x.RealMemberValue)).Max()) - - (64 - GetBitCount())); - } - - - #line default - #line hidden - - #line 1 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - private void WriteFactoryBlock() - { - bool enableDescription = HasMainGenerator && Model.HasDescription; - - - #line default - #line hidden - - #line 7 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("\r\n /// Provides support for parsing \r\n internal sealed partial class StringParser\r\n : IEnumParser<"); - - - #line default - #line hidden - - #line 9 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 9 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(">"); - - - #line default - #line hidden - - #line 9 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(enableDescription ? Append($", IEnumDescriptionParser<{Model.UnderlyingType}>") : new None())); - - - #line default - #line hidden - - #line 10 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("\r\n {\r\n /// Gets the singleton instance of the class.\r\n public static StringParser Instance = new StringParser();\r\n\r\n /// \r\n [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n public "); - - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" BitwiseOr("); - - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" value1, "); - - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" value2) => unchecked(("); - - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 17 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(")(value1 | value2));\r\n\r\n /// \r\n public bool TryParseNumber(ReadOnlySpan value, out "); - - - #line default - #line hidden - - #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 20 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" result) => EnumNumericParser.TryParse(value, out result);\r\n\r\n /// \r\n public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out "); - - - #line default - #line hidden - - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 23 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" result)\r\n {\r\n if (value.IsEmpty)\r\n {\r\n result = 0;\r\n return false;\r\n }\r\n\r\n"); - - - #line default - #line hidden - - #line 31 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - var lookupTable = Model.Values.ToLookup(x => x.MemberName[0]); - - - #line default - #line hidden - - #line 34 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" switch (value[0])\r\n {\r\n"); - - - #line default - #line hidden - - #line 36 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - foreach (var curr in lookupTable) - { - if (char.ToUpperInvariant(curr.Key) == curr.Key && char.ToLowerInvariant(curr.Key) == curr.Key) - { - - - #line default - #line hidden - - #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" case '"); - - - #line default - #line hidden - - #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.Key)); - - - #line default - #line hidden - - #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("':\r\n"); - - - #line default - #line hidden - - #line 43 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - else - { - - - #line default - #line hidden - - #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" case '"); - - - #line default - #line hidden - - #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(char.ToUpperInvariant(curr.Key))); - - - #line default - #line hidden - - #line 48 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("':\r\n case '"); - - - #line default - #line hidden - - #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(char.ToLowerInvariant(curr.Key))); - - - #line default - #line hidden - - #line 49 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("':\r\n"); - - - #line default - #line hidden - - #line 50 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 53 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" switch (value)\r\n {\r\n"); - - - #line default - #line hidden - - #line 55 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - foreach (var enumValue in curr) - { - - - #line default - #line hidden - - #line 59 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" case { } when value.Equals(\""); - - - #line default - #line hidden - - #line 59 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(enumValue.MemberName)); - - - #line default - #line hidden - - #line 59 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("\", comparisonType):\r\n result = "); - - - #line default - #line hidden - - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(enumValue.MemberValue)); - - - #line default - #line hidden - - #line 60 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(";\r\n return true;\r\n"); - - - #line default - #line hidden - - #line 62 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 65 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" }\r\n goto default;\r\n"); - - - #line default - #line hidden - - #line 67 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 70 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" default:\r\n result = 0;\r\n return false;\r\n }\r\n }\r\n"); - - - #line default - #line hidden - - #line 75 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - if (enableDescription) - { - - - #line default - #line hidden - - #line 80 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("\r\n /// \r\n public bool TryParseDescription(ReadOnlySpan value, StringComparison comparisonType, out "); - - - #line default - #line hidden - - #line 81 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 81 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" result)\r\n {\r\n"); - - - #line default - #line hidden - - #line 83 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - if (Model.Values.All(x => x.Description == null)) - { - - - #line default - #line hidden - - #line 87 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" result = default;\r\n return false;\r\n"); - - - #line default - #line hidden - - #line 89 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - else - { - - - #line default - #line hidden - - #line 94 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" switch (value)\r\n {\r\n"); - - - #line default - #line hidden - - #line 96 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - foreach (var curr in Model.Values.Where(x => x.Description != null)) - { - - - #line default - #line hidden - - #line 100 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" case { } s when s.Equals(\""); - - - #line default - #line hidden - - #line 100 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.Description)); - - - #line default - #line hidden - - #line 100 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("\", comparisonType):\r\n result = "); - - - #line default - #line hidden - - #line 101 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - - #line default - #line hidden - - #line 101 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(";\r\n return true;\r\n"); - - - #line default - #line hidden - - #line 103 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 106 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" default:\r\n result = default;\r\n return false;\r\n }\r\n"); - - - #line default - #line hidden - - #line 110 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 113 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" }\r\n"); - - - #line default - #line hidden - - #line 114 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 117 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" }\r\n"); - - - #line default - #line hidden - - #line 118 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - if (HasMainGenerator && Model.HasSerializationValue) - { - - - #line default - #line hidden - - #line 123 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("\r\n /// Provides support for parsing serialized \r\n internal sealed partial class SerializationStringParser : IEnumParser<"); - - - #line default - #line hidden - - #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 124 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(">\r\n {\r\n /// Gets the singleton instance of the class.\r\n public static SerializationStringParser Instance = new SerializationStringParser();\r\n\r\n /// \r\n [MethodImpl(MethodImplOptions.AggressiveInlining)]\r\n public "); - - - #line default - #line hidden - - #line 131 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 131 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" BitwiseOr("); - - - #line default - #line hidden - - #line 131 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 131 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" value1, "); - - - #line default - #line hidden - - #line 131 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 131 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" value2) => unchecked(("); - - - #line default - #line hidden - - #line 131 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 131 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(")(value1 | value2));\r\n\r\n /// \r\n public bool TryParseNumber(ReadOnlySpan value, out "); - - - #line default - #line hidden - - #line 134 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 134 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" result) => EnumNumericParser.TryParse(value, out result);\r\n\r\n /// \r\n public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out "); - - - #line default - #line hidden - - #line 137 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - - #line default - #line hidden - - #line 137 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" result)\r\n {\r\n if (value.IsEmpty)\r\n {\r\n"); - - - #line default - #line hidden - - #line 141 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - var binEmptyValue = Model.Values.FirstOrDefault(x => x.ResolvedSerializedValue.Length == 0); - if (binEmptyValue != null) - { - - - #line default - #line hidden - - #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" result = "); - - - #line default - #line hidden - - #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(binEmptyValue.MemberValue)); - - - #line default - #line hidden - - #line 146 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(";\r\n return true;\r\n"); - - - #line default - #line hidden - - #line 148 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - else - { - - - #line default - #line hidden - - #line 153 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" result = 0;\r\n return false;\r\n"); - - - #line default - #line hidden - - #line 155 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 158 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" }\r\n\r\n"); - - - #line default - #line hidden - - #line 160 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - var binLookupTable = Model.Values.ToLookup(x => x.ResolvedSerializedValue[0]); - - - #line default - #line hidden - - #line 163 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" switch (value[0])\r\n {\r\n"); - - - #line default - #line hidden - - #line 165 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - foreach (var curr in binLookupTable) + if (HasMainGenerator && Model.HasJsonProperty) { - if (char.ToUpperInvariant(curr.Key) == curr.Key && char.ToLowerInvariant(curr.Key) == curr.Key) - { - - - #line default - #line hidden - - #line 171 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" case '"); - - - #line default - #line hidden - - #line 171 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(curr.Key)); - - - #line default - #line hidden - - #line 171 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("':\r\n"); - - - #line default - #line hidden - - #line 172 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - else - { - - - #line default - #line hidden - - #line 177 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" case '"); - - - #line default - #line hidden - - #line 177 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(char.ToUpperInvariant(curr.Key))); - - - #line default - #line hidden - - #line 177 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("':\r\n case '"); - - - #line default - #line hidden - - #line 178 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(char.ToLowerInvariant(curr.Key))); - - - #line default - #line hidden - - #line 178 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("':\r\n"); - - - #line default - #line hidden - - #line 179 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 182 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" switch (value)\r\n {\r\n"); - - - #line default - #line hidden - - #line 184 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - foreach (var enumValue in curr) - { - - - #line default - #line hidden - - #line 188 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" case { } when value.Equals(\""); - - - #line default - #line hidden - - #line 188 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(enumValue.ResolvedSerializedValue)); - - - #line default - #line hidden - - #line 188 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write("\", comparisonType):\r\n result = "); - - - #line default - #line hidden - - #line 189 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(this.ToStringHelper.ToStringWithCulture(enumValue.MemberValue)); - - - #line default - #line hidden - - #line 189 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(";\r\n return true;\r\n"); - - - #line default - #line hidden - - #line 191 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 194 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" }\r\n goto default;\r\n"); - - - #line default - #line hidden - - #line 196 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - - } - - - #line default - #line hidden - - #line 199 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" -this.Write(" default:\r\n result = 0;\r\n return false;\r\n }\r\n }\r\n }\r\n"); - - - #line default - #line hidden - - #line 205 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfo\FactoryBlock.ttinclude" - + WriteLine(); + WriteNames( + "JsonValue", + "serialized members values", + "serialized value", + "serializing", + x => x.ResolvedJsonValue); } } @@ -2864,19 +560,19 @@ private void WriteFactoryBlock() #line default #line hidden - #line 44 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfoWriter.tt" + #line 42 "C:\Users\skarl\source\repos\github\skarllot\EnumUtilities\gen\EnumUtilities.Generators\CodeWriters\EnumInfoWriter.tt" public EnumInfoWriter(StringBuilder builder) : base(builder) { } private bool HasMainGenerator => (Model.SelectedGenerators & SelectedGenerators.MainGenerator) == - SelectedGenerators.MainGenerator; + SelectedGenerators.MainGenerator; public override string GetFileName() => $"{Model.Namespace ?? "_"}.{Model.Name}EnumInfo.g.cs"; protected override bool CanGenerateFor(EnumToGenerate model) => - model.SelectedGenerators != 0; + (model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0; #line default diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumInfoWriter.tt b/gen/EnumUtilities.Generators/CodeWriters/EnumInfoWriter.tt index 9730a01..9dbd5eb 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumInfoWriter.tt +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumInfoWriter.tt @@ -3,9 +3,8 @@ <#@ import namespace="Models" #> <#@ import namespace="System.Text" #> <#@ import namespace="T4CodeWriter" #> +<#@ include file="$(ProjectDir)CodeWriters\EnumInfo\NamesInternal.ttinclude" #> <#@ include file="$(ProjectDir)CodeWriters\EnumInfo\DefaultBlock.ttinclude" #> -<#@ include file="$(ProjectDir)CodeWriters\EnumInfo\ExtensionsBlock.ttinclude" #> -<#@ include file="$(ProjectDir)CodeWriters\EnumInfo\FactoryBlock.ttinclude" #> // #nullable enable @@ -17,29 +16,28 @@ using Raiqub.Generators.EnumUtilities.Parsers; #pragma warning disable CS1591 // publicly visible type or member must be documented <# - if (!string.IsNullOrEmpty(Model.Namespace)) - { - WriteLine($"namespace {Model.Namespace}"); - WriteLine("{"); - PushIndent(); - } + if (!string.IsNullOrEmpty(Model.Namespace)) + { + WriteLine($"namespace {Model.Namespace}"); + WriteLine("{"); + PushIndent(); + } #> +/// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("<#= CurrentAssemblyName.Name #>", "<#= Append($"{CurrentAssemblyName.Version}") #>")] <#= Model.IsPublic ? "public" : "internal" #> static partial class <#= Model.MetadataClassName #> { <# - WriteDefaultBlock(); - WriteExtensionsBlock(); - WriteFactoryBlock(); + WriteDefaultBlock(); #> } <# - if (!string.IsNullOrEmpty(Model.Namespace)) - { - PopIndent(); - WriteLine("}"); - } + if (!string.IsNullOrEmpty(Model.Namespace)) + { + PopIndent(); + WriteLine("}"); + } #> <#+ public EnumInfoWriter(StringBuilder builder) : base(builder) @@ -47,10 +45,10 @@ using Raiqub.Generators.EnumUtilities.Parsers; } private bool HasMainGenerator => (Model.SelectedGenerators & SelectedGenerators.MainGenerator) == - SelectedGenerators.MainGenerator; + SelectedGenerators.MainGenerator; public override string GetFileName() => $"{Model.Namespace ?? "_"}.{Model.Name}EnumInfo.g.cs"; protected override bool CanGenerateFor(EnumToGenerate model) => - model.SelectedGenerators != 0; + (model.SelectedGenerators & SelectedGenerators.MainGenerator) != 0; #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumJsonConverterWriter.cs b/gen/EnumUtilities.Generators/CodeWriters/EnumJsonConverterWriter.cs index 6701055..fe5f917 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumJsonConverterWriter.cs +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumJsonConverterWriter.cs @@ -30,7 +30,7 @@ public override string TransformText() if (Model.JsonConverterGeneratorOptions is null) return string.Empty; - this.Write("// \r\n#nullable enable\r\n\r\nusing System;\r\nusing System.Text.Json;\r\nusing System.Text.Json.Serialization;\r\nusing Raiqub.Generators.EnumUtilities.Formatters;\r\nusing Raiqub.Generators.EnumUtilities.Parsers;\r\n\r\n#pragma warning disable CS1591 // publicly visible type or member must be documented\r\n\r\n"); + this.Write("// \r\n#nullable enable\r\n\r\nusing System;\r\nusing System.Buffers;\r\nusing System.Text.Json;\r\nusing System.Text.Json.Serialization;\r\nusing Raiqub.Generators.EnumUtilities.Formatters;\r\nusing Raiqub.Generators.EnumUtilities.Parsers;\r\n\r\n#pragma warning disable CS1591 // publicly visible type or member must be documented\r\n\r\n"); if (!string.IsNullOrEmpty(Model.Namespace)) { @@ -69,57 +69,13 @@ public override string TransformText() #line default #line hidden - this.Write(">\r\n{\r\n private const int MaxBytesLength = "); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.Max( - x => GetEncodedLength(x.JsonPropertyName ?? x.SerializationValue ?? x.MemberName)))); - - #line default - #line hidden - this.Write(";\r\n private const int MaxCharsLength = "); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.Values.Max( - x => x.JsonPropertyName?.Length ?? x.SerializationValue?.Length ?? x.MemberName.Length))); - - #line default - #line hidden - this.Write(";\r\n\r\n private static readonly "); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".StringFormatter s_stringFormatter = "); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".StringFormatter.Instance;\r\n private static readonly "); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".StringParser s_stringParser = "); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.MetadataClassName)); - - #line default - #line hidden - this.Write(".StringParser.Instance;\r\n\r\n public override "); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); - - #line default - #line hidden - this.Write(" Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\r\n {\r\n if (reader.TokenType == JsonTokenType.String)\r\n return ("); + this.Write(">\r\n{\r\n private const int MaxCharStack = 256;\r\n\r\n public override "); this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - this.Write(")ReadFromString(ref reader);\r\n"); + this.Write(" Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\r\n {\r\n if (reader.TokenType == JsonTokenType.String)\r\n return ReadFromString(ref reader);\r\n"); if (Model.JsonConverterGeneratorOptions.AllowIntegerValues) { @@ -140,183 +96,112 @@ public override string TransformText() #line default #line hidden - this.Write(";\r\n }\r\n\r\n#if NET7_0_OR_GREATER\r\n\r\n public override void Write(Utf8JsonWriter writer, "); + this.Write(";\r\n }\r\n\r\n public override void Write(Utf8JsonWriter writer, "); - this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); - - #line default - #line hidden - this.Write(" value, JsonSerializerOptions options)\r\n {\r\n switch (("); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - this.Write(")value)\r\n {\r\n"); + this.Write(" value, JsonSerializerOptions options)\r\n {\r\n string? jsonString = value.ToJsonString();\r\n if (jsonString is not null)\r\n {\r\n writer.WriteStringValue(jsonString);\r\n }\r\n"); - foreach (var curr in Model.UniqueValues) + if (Model.JsonConverterGeneratorOptions.AllowIntegerValues) { - this.Write(" case "); - - this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + this.Write(" else\r\n {\r\n writer.WriteNumberValue(("); - #line default - #line hidden - this.Write(":\r\n writer.WriteStringValue(\""); - - this.Write(this.ToStringHelper.ToStringWithCulture(curr.JsonPropertyName ?? curr.SerializationValue ?? curr.MemberName)); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); #line default #line hidden - this.Write("\"u8);\r\n break;\r\n"); + this.Write(")value);\r\n }\r\n"); } + else if (Model.JsonConverterGeneratorOptions.DeserializationFailureFallbackValue is not null) + { - this.Write(" default:\r\n string strValue = EnumStringFormatter.GetString(("); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + this.Write(" else\r\n {\r\n jsonString = (("); - #line default - #line hidden - this.Write(")value, s_stringFormatter);\r\n writer.WriteStringValue(strValue);\r\n break;\r\n }\r\n }\r\n\r\n private "); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - this.Write(" ReadFromString(ref Utf8JsonReader reader)\r\n {\r\n int length = reader.HasValueSequence ? checked((int)reader.ValueSequence.Length) : reader.ValueSpan.Length;\r\n if (length > MaxBytesLength)\r\n "); + this.Write(")"); - this.Write(this.ToStringHelper.ToStringWithCulture(AppendFallbackValue(addReturn: true))); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.JsonConverterGeneratorOptions.DeserializationFailureFallbackValue)); #line default #line hidden - this.Write(";\r\n\r\n Span name = stackalloc char[MaxBytesLength];\r\n int charsWritten = reader.CopyString(name);\r\n name = name.Slice(0, charsWritten);\r\n\r\n return name switch\r\n {\r\n"); + this.Write(").ToJsonString();\r\n if (jsonString is not null)\r\n writer.WriteStringValue(jsonString);\r\n else\r\n throw new JsonException();\r\n }\r\n"); - foreach (var curr in Model.Values) + } + else { - this.Write(" "); - - this.Write(this.ToStringHelper.ToStringWithCulture(curr.JsonPropertyName is not null || curr.SerializationValue is not null - ? Append($"\"{curr.JsonPropertyName ?? curr.SerializationValue}\"") - : Append($"\"{curr.MemberName}\""))); - - #line default - #line hidden - this.Write(" => "); - - this.Write(this.ToStringHelper.ToStringWithCulture(NeedNumberCasting() ? Append($"({Model.UnderlyingType})") : Append(""))); - - #line default - #line hidden - - this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - #line default - #line hidden - this.Write(",\r\n"); + this.Write(" else\r\n {\r\n throw new JsonException();\r\n }\r\n"); } - this.Write(" _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out "); + this.Write(" }\r\n\r\n#if NET7_0_OR_GREATER\r\n\r\n private "); - this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - #line default - #line hidden - this.Write(" result) ? result : "); - - this.Write(this.ToStringHelper.ToStringWithCulture(AppendFallbackValue())); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - this.Write("\r\n };\r\n }\r\n\r\n#else\r\n\r\n public override void Write(Utf8JsonWriter writer, "); + this.Write(" ReadFromString(ref Utf8JsonReader reader)\r\n {\r\n int length = reader.HasValueSequence ? checked((int)reader.ValueSequence.Length) : reader.ValueSpan.Length;\r\n\r\n char[]? rented = null;\r\n Span name = length <= MaxCharStack ? stackalloc char[MaxCharStack] : (rented = ArrayPool.Shared.Rent(length));\r\n try\r\n {\r\n int charsWritten = reader.CopyString(name);\r\n name = name.Slice(0, charsWritten);\r\n\r\n bool isParsed = "); this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden - this.Write(" value, JsonSerializerOptions options)\r\n {\r\n switch (("); - - this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); - - #line default - #line hidden - this.Write(")value)\r\n {\r\n"); - - foreach (var curr in Model.UniqueValues) - { - - this.Write(" case "); - - this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); - - #line default - #line hidden - this.Write(":\r\n writer.WriteStringValue(\""); + this.Write("Factory.TryParseJsonString(name, ignoreCase: "); - this.Write(this.ToStringHelper.ToStringWithCulture(curr.JsonPropertyName ?? curr.SerializationValue ?? curr.MemberName)); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.JsonConverterGeneratorOptions.IgnoreCase ? "true" : "false")); #line default #line hidden - this.Write("\");\r\n break;\r\n"); - - } - - this.Write(" default:\r\n string strValue = EnumStringFormatter.GetString(("); + this.Write(", out "); - this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - this.Write(")value, s_stringFormatter);\r\n writer.WriteStringValue(strValue);\r\n break;\r\n }\r\n }\r\n\r\n private "); + this.Write(" result);\r\n if (!isParsed)\r\n {\r\n "); - this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + this.Write(this.ToStringHelper.ToStringWithCulture(AppendFallbackValue(addReturn: true, castToEnum: true))); #line default #line hidden - this.Write(" ReadFromString(ref Utf8JsonReader reader)\r\n {\r\n var name = reader.GetString();\r\n return name switch\r\n {\r\n"); - - foreach (var curr in Model.Values) - { - - this.Write(" "); + this.Write(";\r\n }\r\n\r\n return result;\r\n }\r\n finally\r\n {\r\n if (rented != null)\r\n {\r\n ArrayPool.Shared.Return(rented);\r\n }\r\n }\r\n }\r\n\r\n#else\r\n\r\n private "); - this.Write(this.ToStringHelper.ToStringWithCulture(curr.JsonPropertyName is not null || curr.SerializationValue is not null - ? Append($"\"{curr.JsonPropertyName ?? curr.SerializationValue}\"") - : Append($"\"{curr.MemberName}\""))); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - this.Write(" => "); + this.Write(" ReadFromString(ref Utf8JsonReader reader)\r\n {\r\n var name = reader.GetString();\r\n bool isParsed = "); - this.Write(this.ToStringHelper.ToStringWithCulture(NeedNumberCasting() ? Append($"({Model.UnderlyingType})") : Append(""))); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.Name)); #line default #line hidden + this.Write("Factory.TryParseJsonString(name, ignoreCase: "); - this.Write(this.ToStringHelper.ToStringWithCulture(curr.MemberValue)); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.JsonConverterGeneratorOptions.IgnoreCase ? "true" : "false")); #line default #line hidden - this.Write(",\r\n"); - - } - - this.Write(" _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out "); + this.Write(", out "); - this.Write(this.ToStringHelper.ToStringWithCulture(Model.UnderlyingType)); + this.Write(this.ToStringHelper.ToStringWithCulture(Model.RefName)); #line default #line hidden - this.Write(" result) ? result : "); + this.Write(" result);\r\n if (!isParsed)\r\n {\r\n "); - this.Write(this.ToStringHelper.ToStringWithCulture(AppendFallbackValue())); + this.Write(this.ToStringHelper.ToStringWithCulture(AppendFallbackValue(addReturn: true, castToEnum: true))); #line default #line hidden - this.Write("\r\n };\r\n }\r\n\r\n#endif\r\n"); + this.Write(";\r\n }\r\n\r\n return result;\r\n }\r\n\r\n#endif\r\n"); if (Model.JsonConverterGeneratorOptions.AllowIntegerValues) { @@ -386,7 +271,6 @@ private None AppendFallbackValue(bool addReturn = false, bool castToEnum = false return Append($"{fallbackValue}"); } - private static int GetEncodedLength(string value) => value.Sum(c => c < 128 ? 1 : 6); private bool NeedNumberCasting() => Model.UnderlyingType is "byte" or "short" or "sbyte" or "ushort"; } diff --git a/gen/EnumUtilities.Generators/CodeWriters/EnumJsonConverterWriter.tt b/gen/EnumUtilities.Generators/CodeWriters/EnumJsonConverterWriter.tt index 7a82c4a..a4c154c 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/EnumJsonConverterWriter.tt +++ b/gen/EnumUtilities.Generators/CodeWriters/EnumJsonConverterWriter.tt @@ -11,6 +11,7 @@ #nullable enable using System; +using System.Buffers; using System.Text.Json; using System.Text.Json.Serialization; using Raiqub.Generators.EnumUtilities.Formatters; @@ -30,20 +31,12 @@ using Raiqub.Generators.EnumUtilities.Parsers; [global::System.CodeDom.Compiler.GeneratedCodeAttribute("<#= CurrentAssemblyName.Name #>", "<#= Append($"{CurrentAssemblyName.Version}") #>")] <#= Model.IsPublic ? "public" : "internal" #> sealed class <#= Model.Name #>JsonConverter : JsonConverter<<#= Model.Name #>> { - private const int MaxBytesLength = <#= - Model.Values.Max( - x => GetEncodedLength(x.JsonPropertyName ?? x.SerializationValue ?? x.MemberName)) #>; - private const int MaxCharsLength = <#= - Model.Values.Max( - x => x.JsonPropertyName?.Length ?? x.SerializationValue?.Length ?? x.MemberName.Length) #>; + private const int MaxCharStack = 256; - private static readonly <#= Model.MetadataClassName #>.StringFormatter s_stringFormatter = <#= Model.MetadataClassName #>.StringFormatter.Instance; - private static readonly <#= Model.MetadataClassName #>.StringParser s_stringParser = <#= Model.MetadataClassName #>.StringParser.Instance; - - public override <#= Model.Name #> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override <#= Model.RefName #> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) - return (<#= Model.RefName #>)ReadFromString(ref reader); + return ReadFromString(ref reader); <# if (Model.JsonConverterGeneratorOptions.AllowIntegerValues) { @@ -57,97 +50,90 @@ using Raiqub.Generators.EnumUtilities.Parsers; <#= AppendFallbackValue(addReturn: true, castToEnum: true) #>; } -#if NET7_0_OR_GREATER - - public override void Write(Utf8JsonWriter writer, <#= Model.Name #> value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, <#= Model.RefName #> value, JsonSerializerOptions options) { - switch ((<#= Model.UnderlyingType #>)value) + string? jsonString = value.ToJsonString(); + if (jsonString is not null) { + writer.WriteStringValue(jsonString); + } <# - foreach (var curr in Model.UniqueValues) + if (Model.JsonConverterGeneratorOptions.AllowIntegerValues) { #> - case <#= curr.MemberValue #>: - writer.WriteStringValue("<#= curr.JsonPropertyName ?? curr.SerializationValue ?? curr.MemberName #>"u8); - break; -<# - } -#> - default: - string strValue = EnumStringFormatter.GetString((<#= Model.UnderlyingType #>)value, s_stringFormatter); - writer.WriteStringValue(strValue); - break; + else + { + writer.WriteNumberValue((<#= Model.UnderlyingType #>)value); } +<# } - - private <#= Model.UnderlyingType #> ReadFromString(ref Utf8JsonReader reader) + else if (Model.JsonConverterGeneratorOptions.DeserializationFailureFallbackValue is not null) { - int length = reader.HasValueSequence ? checked((int)reader.ValueSequence.Length) : reader.ValueSpan.Length; - if (length > MaxBytesLength) - <#= AppendFallbackValue(addReturn: true) #>; - - Span name = stackalloc char[MaxBytesLength]; - int charsWritten = reader.CopyString(name); - name = name.Slice(0, charsWritten); - - return name switch +#> + else { + jsonString = ((<#= Model.RefName #>)<#= Model.JsonConverterGeneratorOptions.DeserializationFailureFallbackValue #>).ToJsonString(); + if (jsonString is not null) + writer.WriteStringValue(jsonString); + else + throw new JsonException(); + } <# - foreach (var curr in Model.Values) + } + else { #> - <#= - curr.JsonPropertyName is not null || curr.SerializationValue is not null - ? Append($"\"{curr.JsonPropertyName ?? curr.SerializationValue}\"") - : Append($"\"{curr.MemberName}\"") #> => <#= NeedNumberCasting() ? Append($"({Model.UnderlyingType})") : Append("") #><#= curr.MemberValue #>, + else + { + throw new JsonException(); + } <# } #> - _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out <#= Model.UnderlyingType #> result) ? result : <#= AppendFallbackValue() #> - }; } -#else +#if NET7_0_OR_GREATER - public override void Write(Utf8JsonWriter writer, <#= Model.Name #> value, JsonSerializerOptions options) + private <#= Model.RefName #> ReadFromString(ref Utf8JsonReader reader) { - switch ((<#= Model.UnderlyingType #>)value) + int length = reader.HasValueSequence ? checked((int)reader.ValueSequence.Length) : reader.ValueSpan.Length; + + char[]? rented = null; + Span name = length <= MaxCharStack ? stackalloc char[MaxCharStack] : (rented = ArrayPool.Shared.Rent(length)); + try { -<# - foreach (var curr in Model.UniqueValues) - { -#> - case <#= curr.MemberValue #>: - writer.WriteStringValue("<#= curr.JsonPropertyName ?? curr.SerializationValue ?? curr.MemberName #>"); - break; -<# - } -#> - default: - string strValue = EnumStringFormatter.GetString((<#= Model.UnderlyingType #>)value, s_stringFormatter); - writer.WriteStringValue(strValue); - break; + int charsWritten = reader.CopyString(name); + name = name.Slice(0, charsWritten); + + bool isParsed = <#= Model.Name #>Factory.TryParseJsonString(name, ignoreCase: <#= Model.JsonConverterGeneratorOptions.IgnoreCase ? "true" : "false" #>, out <#= Model.RefName #> result); + if (!isParsed) + { + <#= AppendFallbackValue(addReturn: true, castToEnum: true) #>; + } + + return result; + } + finally + { + if (rented != null) + { + ArrayPool.Shared.Return(rented); + } } } - private <#= Model.UnderlyingType #> ReadFromString(ref Utf8JsonReader reader) +#else + + private <#= Model.RefName #> ReadFromString(ref Utf8JsonReader reader) { var name = reader.GetString(); - return name switch + bool isParsed = <#= Model.Name #>Factory.TryParseJsonString(name, ignoreCase: <#= Model.JsonConverterGeneratorOptions.IgnoreCase ? "true" : "false" #>, out <#= Model.RefName #> result); + if (!isParsed) { -<# - foreach (var curr in Model.Values) - { -#> - <#= - curr.JsonPropertyName is not null || curr.SerializationValue is not null - ? Append($"\"{curr.JsonPropertyName ?? curr.SerializationValue}\"") - : Append($"\"{curr.MemberName}\"") #> => <#= NeedNumberCasting() ? Append($"({Model.UnderlyingType})") : Append("") #><#= curr.MemberValue #>, -<# - } -#> - _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out <#= Model.UnderlyingType #> result) ? result : <#= AppendFallbackValue() #> - }; + <#= AppendFallbackValue(addReturn: true, castToEnum: true) #>; + } + + return result; } #endif @@ -200,6 +186,5 @@ using Raiqub.Generators.EnumUtilities.Parsers; return Append($"{fallbackValue}"); } - private static int GetEncodedLength(string value) => value.Sum(c => c < 128 ? 1 : 6); private bool NeedNumberCasting() => Model.UnderlyingType is "byte" or "short" or "sbyte" or "ushort"; #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Extensions/DefaultBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Extensions/DefaultBlock.ttinclude index 64f1c65..2a8e17b 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/Extensions/DefaultBlock.ttinclude +++ b/gen/EnumUtilities.Generators/CodeWriters/Extensions/DefaultBlock.ttinclude @@ -6,7 +6,8 @@ /// The string representation of the value of this instance. public static string ToStringFast(this <#= Model.RefName #> value) { - return EnumStringFormatter.GetString((<#= Model.UnderlyingType #>)value, s_stringFormatter); + return <#= Model.IsFlags ? "FormatFlagNames" : "GetNameInlined" #>((<#= Model.UnderlyingType #>)value) + ?? ((<#= Model.UnderlyingType #>)value).ToString(); } <#+ if (Model.IsFlags) @@ -16,6 +17,7 @@ /// Determines whether one or more bit fields are set in the current instance. /// An enumeration value. /// if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, . + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasFlagFast(this <#= Model.RefName #> value, <#= Model.RefName #> flag) { return (value & flag) == flag; @@ -29,15 +31,29 @@ /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this <#= Model.RefName #> value) { - return EnumStringFormatter.GetStringLength((<#= Model.UnderlyingType #>)value, s_stringFormatter); + return <#= Model.IsFlags ? "FormatFlagNamesLength" : "GetNameLengthInlined" #>((<#= Model.UnderlyingType #>)value) + ?? EnumNumericFormatter.GetStringLength((<#= Model.UnderlyingType #>)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this <#= Model.RefName #> value) { - return <#= Model.Name #>Validation.IsDefined(value); + return (<#= Model.UnderlyingType #>)value switch + { +<#+ + foreach (var curr in Model.UniqueValues) + { +#> + <#= curr.MemberValue #> => true, +<#+ + } +#> + _ => false + }; } + <#+ + WriteFormatString(x => x.MemberName, "Name"); } #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Extensions/EnumMemberBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Extensions/EnumMemberBlock.ttinclude index ab60ec8..59a3124 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/Extensions/EnumMemberBlock.ttinclude +++ b/gen/EnumUtilities.Generators/CodeWriters/Extensions/EnumMemberBlock.ttinclude @@ -7,13 +7,17 @@ public static string ToEnumMemberValue(this <#= Model.RefName #> value) { - return EnumStringFormatter.GetString((<#= Model.UnderlyingType #>)value, s_serializationStringFormatter); + return <#= Model.IsFlags ? "FormatFlagEnumMemberValues" : "GetEnumMemberValueInlined" #>((<#= Model.UnderlyingType #>)value) + ?? ((<#= Model.UnderlyingType #>)value).ToString(); } public static int GetEnumMemberValueStringLength(this <#= Model.RefName #> value) { - return EnumStringFormatter.GetStringLength((<#= Model.UnderlyingType #>)value, s_serializationStringFormatter); + return <#= Model.IsFlags ? "FormatFlagEnumMemberValuesLength" : "GetEnumMemberValueLengthInlined" #>((<#= Model.UnderlyingType #>)value) + ?? EnumNumericFormatter.GetStringLength((<#= Model.UnderlyingType #>)value); } + <#+ + WriteFormatString(x => x.ResolvedSerializedValue, "EnumMemberValue"); } #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Extensions/FormatStringInternal.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Extensions/FormatStringInternal.ttinclude new file mode 100644 index 0000000..f810cb2 --- /dev/null +++ b/gen/EnumUtilities.Generators/CodeWriters/Extensions/FormatStringInternal.ttinclude @@ -0,0 +1,183 @@ +<#+ + private void WriteFormatString(Func keySelector, string type) + { + if (Model.IsFlags) + { + WriteFormatStringLookup(keySelector, type); + WriteLine(); + } + + WriteInlineFormatString(keySelector, type); + } + + private void WriteFormatStringLookup(Func keySelector, string type) + { + var valuesRanges = Model.GetEnumValueRangesByBitRange(); +#> + private static int? FormatFlag<#= type #>sLength(<#= Model.UnderlyingType #> value) + { + int? fastResult = Get<#= type #>LengthInlined(value); + if (fastResult is not null) + { + return fastResult.Value; + } +<#+ + if (Model.Values.All(x => keySelector(x) != "0")) + { +#> + + if (value == 0) + { + return 1; + } +<#+ + } +#> + + int count = 0, foundItemsCount = 0; +<#+ + foreach (var (i, vRange) in valuesRanges.Index()) + { + if (vRange.Count == 0) + continue; +#> + if (<#= EnumToGenerate.BitRangeConditionStrings[i] #>) + { +<#+ + foreach (var curr in vRange) + { +#> + if ((value & <#= curr.MemberValue #>) == <#= curr.MemberValue #>) + { + value -= <#= curr.MemberValue #>; + count = checked(count + <#= keySelector(curr)!.Length #>); + foundItemsCount++; + if (value == 0) goto CountLength; + } +<#+ + } +#> + } +<#+ + } +#> + + if (value != 0) + { + return null; + } + +CountLength: + const int separatorStringLength = 2; + return checked(count + (separatorStringLength * (foundItemsCount - 1))); + } + + private static readonly string[] s_format<#= type #>s = new string[<#= Model.InvertedValues.Count #>] { <#+ + foreach (var (index, curr) in Model.InvertedValues.Index()) + { + if (index > 0) + Write(", "); + Write($"\"{keySelector(curr)}\""); + } +#> }; + + private static string? FormatFlag<#= type #>s(<#= Model.UnderlyingType #> value) + { + string? result = Get<#= type #>Inlined(value); + if (result is null) + { + Span foundItems = stackalloc int[<#= Model.GetMappedBitCount() #>]; + if (TryFindFlags<#= type #>s(value, foundItems, out int foundItemsCount, out int resultLength)) + { + result = EnumStringFormatter.WriteMultipleFoundFlagsNames(s_format<#= type #>s, foundItems, foundItemsCount, resultLength); + } + } + + return result; + } + + private static bool TryFindFlags<#= type #>s(<#= Model.UnderlyingType #> value, Span foundItems, out int foundItemsCount, out int resultLength) + { + resultLength = 0; + foundItemsCount = 0; +<#+ + foreach (var (i, vRange) in valuesRanges.Index()) + { + if (vRange.Count == 0) + continue; +#> + if (<#= EnumToGenerate.BitRangeConditionStrings[i] #>) + { +<#+ + foreach (var curr in vRange) + { +#> + if ((value & <#= curr.MemberValue #>) == <#= curr.MemberValue #>) + { + value -= <#= curr.MemberValue #>; + resultLength = checked(resultLength + <#= keySelector(curr)!.Length #>); + foundItems[foundItemsCount++] = <#= Model.InvertedValues.IndexOf(curr) #>; + if (value == 0) return true; + } +<#+ + } +#> + } +<#+ + } +#> + + return value == 0; + } +<#+ + } + + private void WriteInlineFormatString(Func keySelector, string type) + { +#> + private static int? Get<#= type #>LengthInlined(<#= Model.UnderlyingType #> value) + { + return value switch + { +<#+ + if (!Model.HasZeroMember) + { +#> + 0 => 1, +<#+ + } + foreach (var curr in Model.UniqueValues) + { +#> + <#= curr.MemberValue #> => <#= keySelector(curr)!.Length #>, +<#+ + } +#> + _ => null + }; + } + + private static string? Get<#= type #>Inlined(<#= Model.UnderlyingType #> value) + { + return value switch + { +<#+ + if (!Model.HasZeroMember) + { +#> + 0 => "0", +<#+ + } + foreach (var curr in Model.UniqueValues) + { +#> + <#= curr.MemberValue #> => "<#= keySelector(curr) #>", +<#+ + } +#> + _ => null + }; + } +<#+ + } +#> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Extensions/InterlockedBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Extensions/InterlockedBlock.ttinclude index 59ab2eb..5574459 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/Extensions/InterlockedBlock.ttinclude +++ b/gen/EnumUtilities.Generators/CodeWriters/Extensions/InterlockedBlock.ttinclude @@ -1,7 +1,7 @@ <#+ private void WriteInterlockedBlock() { - string? underlyingType = GetInterlockedUnderlyingType(); + string? underlyingType = Model.InterlockedUnderlyingType; if (underlyingType is null) return; @@ -112,18 +112,4 @@ <#+ } } - - private string? GetInterlockedUnderlyingType() - { - return Model.UnderlyingType switch - { - "int" => "int", - "long" => "long", - "uint" => "int", - "ulong" => "long", - _ => null - }; - } - - private bool IsInterlockedSupported() => GetInterlockedUnderlyingType() != null; #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Extensions/JsonBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Extensions/JsonBlock.ttinclude new file mode 100644 index 0000000..3b02948 --- /dev/null +++ b/gen/EnumUtilities.Generators/CodeWriters/Extensions/JsonBlock.ttinclude @@ -0,0 +1,23 @@ +<#+ + private void WriteJsonBlock() + { + if (!Model.HasJsonProperty && (Model.SelectedGenerators & SelectedGenerators.JsonConverter) == 0) + return; +#> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? ToJsonString(this <#= Model.RefName #> value) + { + return <#= Model.IsFlags ? "FormatFlagJsonStrings" : "GetJsonStringInlined" #>((<#= Model.UnderlyingType #>)value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? GetJsonStringLength(this <#= Model.RefName #> value) + { + return <#= Model.IsFlags ? "FormatFlagJsonStringsLength" : "GetJsonStringLengthInlined" #>((<#= Model.UnderlyingType #>)value); + } + +<#+ + WriteFormatString(x => x.ResolvedJsonValue, "JsonString"); + } +#> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Factory/DefaultBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Factory/DefaultBlock.ttinclude index 1ba4d47..4f4b231 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/Factory/DefaultBlock.ttinclude +++ b/gen/EnumUtilities.Generators/CodeWriters/Factory/DefaultBlock.ttinclude @@ -13,9 +13,9 @@ /// is empty or does not represent a valid value. public static <#= Model.RefName #> Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; } /// @@ -28,8 +28,8 @@ /// is empty or does not represent a valid value. public static <#= Model.RefName #> Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; } /// @@ -44,8 +44,8 @@ public static <#= Model.RefName #>? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; } /// @@ -62,7 +62,8 @@ /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out <#= Model.RefName #> result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } /// @@ -78,7 +79,8 @@ /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out <#= Model.RefName #> result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), <#= GetComparisonExpression(false) #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } /// @@ -93,7 +95,7 @@ /// public static <#= Model.RefName #>? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out <#= Model.RefName #> result) ? result : null; + return TryParseName(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; } /// @@ -110,7 +112,8 @@ /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out <#= Model.RefName #> result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } /// @@ -126,7 +129,8 @@ /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out <#= Model.RefName #> result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, <#= GetComparisonExpression(false) #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } /// @@ -141,21 +145,86 @@ /// public static <#= Model.RefName #>? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out <#= Model.RefName #> result) ? result : null; + return TryParseName(value, <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out <#= Model.RefName #> result) +<#+ + WriteTryParse(x => x.MemberName, "Name"); +#> + + /// + /// Converts the string representation of the name or numeric value of one or more enumerated constants to + /// an equivalent enumerated object. The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration name or underlying value to convert. + /// One of the enumeration values that specifies how the strings will be compared. + /// + /// When this method returns, result contains an object of type <#= Model.Name #> whose value is represented by value + /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the + /// underlying type of <#= Model.Name #>. Note that this value need not be a member of the <#= Model.Name #> enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + /// is not a value. + [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] + public static bool TryParse( + [NotNullWhen(true)] string? name, + StringComparison comparisonType, + out <#= Model.RefName #> result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out <#= Model.UnderlyingType #> number); - if (!success) - { - result = 0; - return false; - } + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); + } - result = (<#= Model.RefName #>)number; - return true; + /// + /// Converts the string representation of the name or numeric value of one or more enumerated constants to + /// an equivalent enumerated object. The return value indicates whether the conversion succeeded. + /// + /// The case-insensitive string representation of the enumeration name or underlying value to convert. + /// + /// When this method returns, result contains an object of type <#= Model.Name #> whose value is represented by value + /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the + /// underlying type of <#= Model.Name #>. Note that this value need not be a member of the <#= Model.Name #> enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] + public static bool TryParseIgnoreCase( + [NotNullWhen(true)] string? name, + out <#= Model.RefName #> result) + { + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), <#= GetComparisonExpression(true) #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); + } + + /// + /// Converts the string representation of the name or numeric value of one or more enumerated constants to + /// an equivalent enumerated object. + /// + /// The case-insensitive string representation of the enumeration name or underlying value to convert. + /// + /// Contains an object of type <#= Model.Name #> whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains null value. + /// + [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] + public static <#= Model.RefName #>? TryParseIgnoreCase(string? name) + { + return TryParseName(name.AsSpan(), <#= GetComparisonExpression(true) #>, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; + } + + /// + /// Converts the string representation of the name or numeric value of one or more enumerated constants to + /// an equivalent enumerated object. + /// + /// The string representation of the enumeration name or underlying value to convert. + /// One of the enumeration values that specifies how the strings will be compared. + /// + /// Contains an object of type <#= Model.Name #> whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains null value. + /// + /// is not a value. + [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] + public static <#= Model.RefName #>? TryParse(string? name, StringComparison comparisonType) + { + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; } <#+ } diff --git a/gen/EnumUtilities.Generators/CodeWriters/Factory/DescriptionBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Factory/DescriptionBlock.ttinclude index e8f6e93..bd67afa 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/Factory/DescriptionBlock.ttinclude +++ b/gen/EnumUtilities.Generators/CodeWriters/Factory/DescriptionBlock.ttinclude @@ -7,67 +7,60 @@ public static <#= Model.RefName #> CreateFromDescription(string description, StringComparison comparisonType = StringComparison.Ordinal) { - if (description is null) ThrowArgumentNullException(nameof(description)); - TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); - return result; + if (description is null) ThrowHelper.ThrowArgumentNullException(nameof(description)); + TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; } public static <#= Model.RefName #> CreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal) { - TryCreateFromDescription(description, comparisonType, throwOnFailure: true, out var result); - return result; + TryParseDescription(description, comparisonType, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; } [return: NotNullIfNotNull("description")] public static <#= Model.RefName #>? CreateFromDescriptionOrNull(string? description, StringComparison comparisonType = StringComparison.Ordinal) { if (description is null) return null; - TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); - return result; + TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; } public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, StringComparison comparisonType, out <#= Model.RefName #> result) { - return TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, out <#= Model.RefName #> result) { - return TryCreateFromDescription(description.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } public static <#= Model.RefName #>? TryCreateFromDescription(string? description, StringComparison comparisonType = StringComparison.Ordinal) { - return TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out <#= Model.RefName #> result) ? result : null; + return TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; } public static bool TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType, out <#= Model.RefName #> result) { - return TryCreateFromDescription(description, comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description, comparisonType, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } public static bool TryCreateFromDescription(ReadOnlySpan description, out <#= Model.RefName #> result) { - return TryCreateFromDescription(description, StringComparison.Ordinal, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } public static <#= Model.RefName #>? TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal) { - return TryCreateFromDescription(description, comparisonType, throwOnFailure: false, out <#= Model.RefName #> result) ? result : null; + return TryParseDescription(description, comparisonType, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; } - private static bool TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType, bool throwOnFailure, out <#= Model.RefName #> result) - { - bool success = EnumStringParser.TryParseDescription(description, s_stringParser, comparisonType, throwOnFailure, out <#= Model.UnderlyingType #> number); - if (!success) - { - result = 0; - return false; - } - - result = (<#= Model.RefName #>)number; - return true; - } <#+ + WriteTryParse(x => x.Description, "Description", "description", allowNumbers: false); } #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Factory/EnumMemberBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Factory/EnumMemberBlock.ttinclude index ade440a..d863b64 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/Factory/EnumMemberBlock.ttinclude +++ b/gen/EnumUtilities.Generators/CodeWriters/Factory/EnumMemberBlock.ttinclude @@ -15,9 +15,9 @@ /// is empty or does not represent a valid value. public static <#= Model.RefName #> ParseFromEnumMemberValue(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseEnumMemberValue(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; } /// @@ -29,8 +29,8 @@ /// is empty or does not represent a valid value. public static <#= Model.RefName #> ParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value, <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; } /// @@ -44,8 +44,8 @@ public static <#= Model.RefName #>? ParseFromEnumMemberValueOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; } /// @@ -62,7 +62,8 @@ /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, bool ignoreCase, out <#= Model.RefName #> result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } /// @@ -78,7 +79,8 @@ /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, out <#= Model.RefName #> result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), <#= GetComparisonExpression(false) #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } /// @@ -92,7 +94,7 @@ /// public static <#= Model.RefName #>? TryParseFromEnumMemberValue(string? value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out <#= Model.RefName #> result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; } /// @@ -109,7 +111,8 @@ /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, out <#= Model.RefName #> result) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } /// @@ -125,7 +128,8 @@ /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out <#= Model.RefName #> result) { - return TryParseFromEnumMemberValue(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, <#= GetComparisonExpression(false) #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } /// @@ -139,26 +143,12 @@ /// public static <#= Model.RefName #>? TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out <#= Model.RefName #> result) ? result : null; + return TryParseEnumMemberValue(value, <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; } - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out <#= Model.RefName #> result) - { - return TryParseFromEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure, out result); - } - - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out <#= Model.RefName #> result) - { - bool success = EnumStringParser.TryParse(value, s_serializationStringParser, comparisonType, throwOnFailure, out <#= Model.UnderlyingType #> number); - if (!success) - { - result = 0; - return false; - } - - result = (<#= Model.RefName #>)number; - return true; - } +<#+ + WriteTryParse(x => x.ResolvedSerializedValue, "EnumMemberValue"); +#> /// /// Converts the string representation of the serialized value to an equivalent enumerated object. @@ -179,7 +169,8 @@ StringComparison comparisonType, out <#= Model.RefName #> result) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); } /// @@ -196,7 +187,7 @@ [Obsolete("Use TryParseFromEnumMemberValue overload with 'ignoreCase' parameter")] public static <#= Model.RefName #>? TryParseFromEnumMemberValue(string? value, StringComparison comparisonType) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out <#= Model.RefName #> result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; } <#+ } diff --git a/gen/EnumUtilities.Generators/CodeWriters/Factory/JsonBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Factory/JsonBlock.ttinclude new file mode 100644 index 0000000..96aebfe --- /dev/null +++ b/gen/EnumUtilities.Generators/CodeWriters/Factory/JsonBlock.ttinclude @@ -0,0 +1,152 @@ +<#+ + public void WriteJsonBlock() + { + if (!Model.HasJsonProperty && (Model.SelectedGenerators & SelectedGenerators.JsonConverter) == 0) + return; +#> + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value. Note that this value need not be a member of the <#= Model.Name #> enumeration. + /// is . + /// is empty or does not represent a valid value. + public static <#= Model.RefName #> ParseJsonString(string value, bool ignoreCase = false) + { + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseJsonString(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value. Note that this value need not be a member of the <#= Model.Name #> enumeration. + /// is empty or does not represent a valid value. + public static <#= Model.RefName #> ParseJsonString(ReadOnlySpan value, bool ignoreCase = false) + { + TryParseJsonString(value, <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value or null. Note that this value need not be a member of the <#= Model.Name #> enumeration. + /// is empty or does not represent a valid value. + [return: NotNullIfNotNull("value")] + public static <#= Model.RefName #>? ParseJsonStringOrNull(string? value, bool ignoreCase = false) + { + if (value is null) return null; + TryParseJsonString(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: true, out var result); + return (<#= Model.RefName #>)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// When this method returns, result contains an object of type <#= Model.Name #> whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of <#= Model.Name #>. Note that this value need not be a member of the <#= Model.Name #> enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString([NotNullWhen(true)] string? value, bool ignoreCase, out <#= Model.RefName #> result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// + /// When this method returns, result contains an object of type <#= Model.Name #> whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of <#= Model.Name #>. Note that this value need not be a member of the <#= Model.Name #> enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString([NotNullWhen(true)] string? value, out <#= Model.RefName #> result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value.AsSpan(), <#= GetComparisonExpression(false) #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// Contains an object of type <#= Model.Name #> whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains a null value. + /// + public static <#= Model.RefName #>? TryParseJsonString(string? value, bool ignoreCase = false) + { + return TryParseJsonString(value.AsSpan(), <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// When this method returns, result contains an object of type <#= Model.Name #> whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of <#= Model.Name #>. Note that this value need not be a member of the <#= Model.Name #> enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString(ReadOnlySpan value, bool ignoreCase, out <#= Model.RefName #> result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value, <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// + /// When this method returns, result contains an object of type <#= Model.Name #> whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of <#= Model.Name #>. Note that this value need not be a member of the <#= Model.Name #> enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString(ReadOnlySpan value, out <#= Model.RefName #> result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value, <#= GetComparisonExpression(false) #>, throwOnFailure: false, out Unsafe.As<<#= Model.RefName #>, <#= Model.UnderlyingType #>>(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// Contains an object of type <#= Model.Name #> whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains a null value. + /// + public static <#= Model.RefName #>? TryParseJsonString(ReadOnlySpan value, bool ignoreCase = false) + { + return TryParseJsonString(value, <#= GetIgnoreCaseToComparisonExpression() #>, throwOnFailure: false, out var result) ? (<#= Model.RefName #>?)result : null; + } + +<#+ + WriteTryParse(x => x.ResolvedJsonValue, "JsonString", allowNumbers: false); + } +#> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Factory/LegacyDefaultBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Factory/LegacyDefaultBlock.ttinclude deleted file mode 100644 index 8bfdcfb..0000000 --- a/gen/EnumUtilities.Generators/CodeWriters/Factory/LegacyDefaultBlock.ttinclude +++ /dev/null @@ -1,88 +0,0 @@ -<#+ - private void WriteLegacyDefaultBlock() - { -#> - - /// - /// Converts the string representation of the name or numeric value of one or more enumerated constants to - /// an equivalent enumerated object. The return value indicates whether the conversion succeeded. - /// - /// The string representation of the enumeration name or underlying value to convert. - /// One of the enumeration values that specifies how the strings will be compared. - /// - /// When this method returns, result contains an object of type <#= Model.Name #> whose value is represented by value - /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the - /// underlying type of <#= Model.Name #>. Note that this value need not be a member of the <#= Model.Name #> enumeration. - /// - /// true if the value parameter was converted successfully; otherwise, false. - /// is not a value. - [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] - public static bool TryParse( - [NotNullWhen(true)] string? name, - StringComparison comparisonType, - out <#= Model.RefName #> result) - { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out <#= Model.UnderlyingType #> number); - if (!success) - { - result = 0; - return false; - } - - result = (<#= Model.RefName #>)number; - return true; - } - - /// - /// Converts the string representation of the name or numeric value of one or more enumerated constants to - /// an equivalent enumerated object. The return value indicates whether the conversion succeeded. - /// - /// The case-insensitive string representation of the enumeration name or underlying value to convert. - /// - /// When this method returns, result contains an object of type <#= Model.Name #> whose value is represented by value - /// if the parse operation succeeds. If the parse operation fails, result contains the default value of the - /// underlying type of <#= Model.Name #>. Note that this value need not be a member of the <#= Model.Name #> enumeration. - /// - /// true if the value parameter was converted successfully; otherwise, false. - [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] - public static bool TryParseIgnoreCase( - [NotNullWhen(true)] string? name, - out <#= Model.RefName #> result) - { - return TryParse(name.AsSpan(), ignoreCase: true, out result); - } - - /// - /// Converts the string representation of the name or numeric value of one or more enumerated constants to - /// an equivalent enumerated object. - /// - /// The case-insensitive string representation of the enumeration name or underlying value to convert. - /// - /// Contains an object of type <#= Model.Name #> whose value is represented by value if the parse operation succeeds. - /// If the parse operation fails, result contains null value. - /// - [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] - public static <#= Model.RefName #>? TryParseIgnoreCase(string? name) - { - return TryParse(name.AsSpan(), ignoreCase: true, out <#= Model.RefName #> result) ? result : null; - } - - /// - /// Converts the string representation of the name or numeric value of one or more enumerated constants to - /// an equivalent enumerated object. - /// - /// The string representation of the enumeration name or underlying value to convert. - /// One of the enumeration values that specifies how the strings will be compared. - /// - /// Contains an object of type <#= Model.Name #> whose value is represented by value if the parse operation succeeds. - /// If the parse operation fails, result contains null value. - /// - /// is not a value. - [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] - public static <#= Model.RefName #>? TryParse(string? name, StringComparison comparisonType) - { - return TryParse(name, comparisonType, out <#= Model.RefName #> result) ? result : null; - } -<#+ - } -#> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Factory/MiscellaneousBlock.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Factory/MiscellaneousBlock.ttinclude index a19c48a..3e2c25d 100644 --- a/gen/EnumUtilities.Generators/CodeWriters/Factory/MiscellaneousBlock.ttinclude +++ b/gen/EnumUtilities.Generators/CodeWriters/Factory/MiscellaneousBlock.ttinclude @@ -36,12 +36,6 @@ #> }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } <#+ } #> diff --git a/gen/EnumUtilities.Generators/CodeWriters/Factory/TryParseInternal.ttinclude b/gen/EnumUtilities.Generators/CodeWriters/Factory/TryParseInternal.ttinclude new file mode 100644 index 0000000..bd926ff --- /dev/null +++ b/gen/EnumUtilities.Generators/CodeWriters/Factory/TryParseInternal.ttinclude @@ -0,0 +1,214 @@ +<#+ + private static string GetIgnoreCaseToComparisonExpression() + => "ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal"; + + private static string GetComparisonExpression(bool ignoreCase) + => ignoreCase ? "StringComparison.OrdinalIgnoreCase" : "StringComparison.Ordinal"; + + private void WriteTryParse( + Func keySelector, + string type, + string parameterName = "value", + bool allowNumbers = true) + { +#> + private static bool TryParse<#= type #>(ReadOnlySpan <#= parameterName #>, StringComparison comparisonType, bool throwOnFailure, out <#= Model.UnderlyingType #> result) + { + if (!<#= parameterName #>.IsEmpty) + { +<#+ + if (allowNumbers) + { +#> + char c = <#= parameterName #>[0]; + if (char.IsWhiteSpace(c)) + { + <#= parameterName #> = <#= parameterName #>.TrimStart(); + if (<#= parameterName #>.IsEmpty) + { + goto ParseFailure; + } + + c = <#= parameterName #>[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumeric<#= type #>(<#= parameterName #>, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(<#= parameterName #>, out result); + if (success) + { + return true; + } + +<#+ + } +#> + return TryParseNonNumeric<#= type #>(<#= parameterName #>, comparisonType, throwOnFailure, out result); + } + +<#+ + if (allowNumbers) + { +#> + ParseFailure: +<#+ + } +#> + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(<#= parameterName #>)); + } + + result = 0; + return false; + } +<#+ + WriteLine(); + WriteTryParseNonNumeric(type, parameterName); + WriteLine(); + WriteTryParseLookup(keySelector, type); + } + + private void WriteTryParseNonNumeric(string type, string parameterName = "value") + { + if (Model.IsFlags) + { +#> + private static bool TryParseNonNumeric<#= type #>(ReadOnlySpan <#= parameterName #>, StringComparison comparisonType, bool throwOnFailure, out <#= Model.UnderlyingType #> result) + { + bool parsed = true; + <#= Model.UnderlyingType #> localResult = 0; + foreach (var item in new FlagsEnumTokenizer(<#= parameterName #>)) + { + bool success = TryParseSingle<#= type #>(item, comparisonType, out <#= Model.UnderlyingType #> singleValue); + if (!success) + { + parsed = false; + break; + } + + localResult |= singleValue; + } + + if (parsed) + { + result = localResult; + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(<#= parameterName #>, nameof(<#= parameterName #>)); + } + + result = 0; + return false; + } +<#+ + } + else + { +#> + private static bool TryParseNonNumeric<#= type #>(ReadOnlySpan <#= parameterName #>, StringComparison comparisonType, bool throwOnFailure, out <#= Model.UnderlyingType #> result) + { + bool success = TryParseSingle<#= type #>(<#= parameterName #>, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(<#= parameterName #>, nameof(<#= parameterName #>)); + } + + return false; + } +<#+ + } + } + + private void WriteTryParseLookup( + Func keySelector, + string type) + { +#> + private static bool TryParseSingle<#= type #>(ReadOnlySpan value, StringComparison comparisonType, out <#= Model.UnderlyingType #> result) + { + if (value.IsEmpty) + { +<#+ + var binEmptyValue = Model.Values.FirstOrDefault(x => keySelector(x)?.Length == 0); + if (binEmptyValue != null) + { +#> + result = <#= binEmptyValue.MemberValue #>; + return true; +<#+ + } + else + { +#> + result = 0; + return false; +<#+ + } +#> + } + +<#+ + var lookupTable = Model.Values.Where(x => keySelector(x)?.Length > 0).ToLookup(x => keySelector(x)![0]); +#> + switch (value[0]) + { +<#+ + foreach (var curr in lookupTable.OrderBy(x => x.Key)) + { + if (char.IsSurrogate(curr.Key) || char.IsControl(curr.Key)) + { +#> + case '\u<#= ((int)curr.Key).ToString("x4") #>': +<#+ + } + else if (char.ToUpperInvariant(curr.Key) == curr.Key && char.ToLowerInvariant(curr.Key) == curr.Key) + { +#> + case '<#= curr.Key #>': +<#+ + } + else + { +#> + case '<#= char.ToUpperInvariant(curr.Key) #>': + case '<#= char.ToLowerInvariant(curr.Key) #>': +<#+ + } +#> + switch (value) + { +<#+ + foreach (var enumValue in curr) + { +#> + case { } when value.Equals("<#= keySelector(enumValue) #>", comparisonType): + result = <#= enumValue.MemberValue #>; + return true; +<#+ + } +#> + } + break; +<#+ + } +#> + } + + result = 0; + return false; + } +<#+ + } +#> diff --git a/gen/EnumUtilities.Generators/Models/EnumToGenerate.cs b/gen/EnumUtilities.Generators/Models/EnumToGenerate.cs index de71307..c25c92a 100644 --- a/gen/EnumUtilities.Generators/Models/EnumToGenerate.cs +++ b/gen/EnumUtilities.Generators/Models/EnumToGenerate.cs @@ -17,11 +17,19 @@ public sealed record EnumToGenerate( ImmutableArray Locations) : ILocalizableSource { + private List? _invertedValues; + public string MetadataClassName => Name.Contains("Metadata") ? $"{Name}Info" : $"{Name}Metadata"; public string RefName { get; } = ContainingType is not null ? $"{ContainingType.Name}.{Name}" : Name; - public IEnumerable UniqueValues => - Values.DistinctBy(static it => it.MemberValue, StringComparer.Ordinal); + public List UniqueValues { get; } = + Values.DistinctBy(static it => it.MemberValue, StringComparer.Ordinal).ToList(); + + public List InvertedValues => + _invertedValues ??= Values + .DistinctBy(x => x.RealMemberValue) + .OrderByDescending(x => x.RealMemberValue) + .ToList(); public bool HasSerializationValue => Values.Exists(static it => it.SerializationValue != null); @@ -41,6 +49,25 @@ public sealed record EnumToGenerate( public bool HasDisplayGroupName => Values.Exists(static it => it.Display?.GroupName != null); + public bool HasJsonProperty => + Values.Exists(static it => it.JsonPropertyName != null); + + public bool HasZeroMember { get; } = + Values.Any(x => x.RealMemberValue == 0); + + private int BitCount { get; } = UnderlyingType switch + { + "byte" => 8, + "sbyte" => 8, + "short" => 16, + "ushort" => 16, + "int" => 32, + "uint" => 32, + "long" => 64, + "ulong" => 64, + _ => 64, + }; + public static EnumToGenerate? FromSymbol(ISymbol symbol) { if (symbol is not INamedTypeSymbol typeSymbol || @@ -83,4 +110,57 @@ typeSymbol.ContainingType is enumValues, typeSymbol.Locations); } + + public static string[] BitRangeConditionStrings { get; } = + ["value > 0xffff_ffff_ffff", "value > 0xffff_ffff", "value > 0xffff", "true"]; + + public List[] GetEnumValueRangesByBitRange() + { + var h2Values = BitCount == 64 + ? InvertedValues + .Where(x => x.RealMemberValue > 0x0000_ffff_ffff_ffffUL) + .ToList() + : []; + var h1Values = BitCount == 64 + ? InvertedValues + .Where( + x => x.RealMemberValue > 0x0000_0000_ffff_ffffUL & x.RealMemberValue <= 0x0000_ffff_ffff_ffffUL) + .ToList() + : []; + var l2Values = BitCount >= 32 + ? InvertedValues + .Where( + x => x.RealMemberValue > 0x0000_0000_0000_ffffUL & x.RealMemberValue <= 0x0000_0000_ffff_ffffUL) + .ToList() + : []; + var l1Values = BitCount >= 16 + ? InvertedValues + .Where( + x => x.RealMemberValue > 0x0000_0000_0000_0000UL & x.RealMemberValue <= 0x0000_0000_0000_ffffUL) + .ToList() + : []; + return [h2Values, h1Values, l2Values, l1Values]; + } + + public int GetMappedBitCount() + { + if (Values.Any(x => x.MemberValue[0] == '-')) + return BitCount; + + return BitCount - + (BitOperations.LeadingZeroCount(Values.Select(x => x.RealMemberValue).Max()) - + (64 - BitCount)); + } + + public string? InterlockedUnderlyingType => + UnderlyingType switch + { + "int" => "int", + "long" => "long", + "uint" => "int", + "ulong" => "long", + _ => null, + }; + + public bool IsInterlockedSupported() => InterlockedUnderlyingType != null; } diff --git a/gen/EnumUtilities.Generators/Models/EnumValue.cs b/gen/EnumUtilities.Generators/Models/EnumValue.cs index 617ee64..f8bcbe7 100644 --- a/gen/EnumUtilities.Generators/Models/EnumValue.cs +++ b/gen/EnumUtilities.Generators/Models/EnumValue.cs @@ -1,32 +1,36 @@ -using Microsoft.CodeAnalysis; +using System.Runtime.CompilerServices; +using Microsoft.CodeAnalysis; using Raiqub.Generators.EnumUtilities.Common; namespace Raiqub.Generators.EnumUtilities.Models; public sealed class EnumValue { - private EnumValue(string memberName, string memberValue, object realMemberValue) + private EnumValue(string memberName, string memberValue, object realMemberValue, int index) { MemberName = memberName; MemberValue = memberValue; - RealMemberValue = realMemberValue; + RealMemberValue = ConvertToUInt64(realMemberValue); + Index = index; } public string MemberName { get; } public string MemberValue { get; } - public object RealMemberValue { get; } + public ulong RealMemberValue { get; set; } + public int Index { get; } public string? SerializationValue { get; set; } public string? Description { get; set; } public DisplayAttribute? Display { get; set; } public string? JsonPropertyName { get; set; } public string ResolvedSerializedValue => SerializationValue ?? MemberName; + public string ResolvedJsonValue => JsonPropertyName ?? SerializationValue ?? MemberName; - public static EnumValue? FromSymbol(ISymbol symbol) + public static EnumValue? FromSymbol(ISymbol symbol, int index) { if (symbol is not IFieldSymbol { ConstantValue: not null } field) return null; - var result = new EnumValue(field.Name, field.ConstantValue.ToString(), field.ConstantValue); + var result = new EnumValue(field.Name, field.ConstantValue.ToString(), field.ConstantValue, index); foreach (var attribute in field.GetAttributes()) { @@ -49,4 +53,33 @@ private EnumValue(string memberName, string memberValue, object realMemberValue) return result; } + + private static ulong ConvertToUInt64(object realMemberValue) + { + long tmp; + switch (realMemberValue) + { + case int v: + tmp = v; + return Unsafe.As(ref tmp); + case uint v: + return v; + case long v: + return Unsafe.As(ref v); + case ulong v: + return v; + case byte v: + return v; + case sbyte v: + tmp = v; + return Unsafe.As(ref tmp); + case short v: + tmp = v; + return Unsafe.As(ref tmp); + case ushort v: + return v; + default: + return Convert.ToUInt64(realMemberValue); + } + } } diff --git a/gen/EnumUtilities.Generators/Models/JsonConverterGeneratorOptions.cs b/gen/EnumUtilities.Generators/Models/JsonConverterGeneratorOptions.cs index 9f95221..2134cec 100644 --- a/gen/EnumUtilities.Generators/Models/JsonConverterGeneratorOptions.cs +++ b/gen/EnumUtilities.Generators/Models/JsonConverterGeneratorOptions.cs @@ -5,6 +5,7 @@ namespace Raiqub.Generators.EnumUtilities.Models; public sealed record JsonConverterGeneratorOptions( bool AllowIntegerValues, + bool IgnoreCase, object? DeserializationFailureFallbackValue) { public static JsonConverterGeneratorOptions? FromSymbol(INamedTypeSymbol typeSymbol) @@ -17,6 +18,8 @@ public sealed record JsonConverterGeneratorOptions( return new JsonConverterGeneratorOptions( attributeData.GetNamedArgument( nameof(JsonConverterGeneratorAttribute.AllowIntegerValues)) as bool? ?? true, + attributeData.GetNamedArgument( + nameof(JsonConverterGeneratorAttribute.IgnoreCase)) as bool? ?? false, attributeData.GetNamedArgument( nameof(JsonConverterGeneratorAttribute.DeserializationFailureFallbackValue))); } diff --git a/perf/Directory.Build.props b/perf/Directory.Build.props new file mode 100644 index 0000000..aaba3aa --- /dev/null +++ b/perf/Directory.Build.props @@ -0,0 +1,10 @@ + + + + false + false + $(MSBuildProjectName) + $(RootNamespace) + false + + diff --git a/perf/EnumUtilities.Benchmark/Config/BenchmarkConfig.cs b/perf/EnumUtilities.Benchmark/Config/BenchmarkConfig.cs new file mode 100644 index 0000000..7b3aa75 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Config/BenchmarkConfig.cs @@ -0,0 +1,25 @@ +using BenchmarkDotNet.Columns; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Exporters; +using BenchmarkDotNet.Loggers; + +namespace EnumUtilities.Benchmark.Config; + +public class BenchmarkConfig : ManualConfig +{ + private readonly IConfig _defaultConfig = DefaultConfig.Instance; + + public BenchmarkConfig() + { + AddColumnProvider(DefaultColumnProviders.Instance) + .AddExporter(MarkdownExporter.GitHub) + .AddLogger(ConsoleLogger.Default) + .AddAnalyser(_defaultConfig.GetAnalysers().ToArray()) + .AddValidator(_defaultConfig.GetValidators().ToArray()) + .WithSummaryStyle(_defaultConfig.SummaryStyle) + .WithOption(ConfigOptions.DisableLogFile, true) + .WithArtifactsPath(Path.Combine(RuntimeContext.SolutionDirectory, "docs", "benchmarks")); + + HideColumns(Column.Arguments, Column.NuGetReferences); + } +} diff --git a/perf/EnumUtilities.Benchmark/Config/RuntimeContext.cs b/perf/EnumUtilities.Benchmark/Config/RuntimeContext.cs new file mode 100644 index 0000000..04b21e1 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Config/RuntimeContext.cs @@ -0,0 +1,22 @@ +using System.Reflection; + +namespace EnumUtilities.Benchmark.Config; + +internal static class RuntimeContext +{ + public static string SolutionDirectory { get; } = ResolveSolutionDirectory(); + + private static string ResolveSolutionDirectory() + { + var assemblyFolder = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory; + for (var currDir = assemblyFolder; currDir != null; currDir = currDir.Parent) + { + if (!currDir.EnumerateFiles("*.sln", SearchOption.TopDirectoryOnly).Any()) + continue; + + return currDir.FullName; + } + + return string.Empty; + } +} diff --git a/perf/EnumUtilities.Benchmark/EnumUtilities.Benchmark.csproj b/perf/EnumUtilities.Benchmark/EnumUtilities.Benchmark.csproj new file mode 100644 index 0000000..71cfb0b --- /dev/null +++ b/perf/EnumUtilities.Benchmark/EnumUtilities.Benchmark.csproj @@ -0,0 +1,21 @@ + + + Exe + net8.0 + Release + AnyCPU + true + + + + + + + + + + + + diff --git a/perf/EnumUtilities.Benchmark/Models/Elf.cs b/perf/EnumUtilities.Benchmark/Models/Elf.cs new file mode 100644 index 0000000..053a853 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Models/Elf.cs @@ -0,0 +1,42 @@ +using NetEscapades.EnumGenerators; +using Raiqub.Generators.EnumUtilities; + +namespace EnumUtilities.Benchmark.Models; + +[EnumExtensions(ExtensionClassName = "ElfNetEscapades")] +[EnumGenerator] +public enum Elf +{ + Galadriel = 1, + Elrond, + Arwen, + Legolas, + Thranduil, + Celeborn, + Glorfindel, + Erestor, + Cirdan, + GilGalad, + Haldir, + Elladan, + Elrohir, + Lindir, + Oropher, + Amroth, + Galdor, + Finrod, + Ecthelion, + Idril, + Luthien, + Aegnor, + Fingolfin, + Turgon, + Maedhros, + Maglor, + Caranthir, + Amras, + Amrod, + Feanor, + Galathil, + Aredhel +} diff --git a/perf/EnumUtilities.Benchmark/Models/Permissions.cs b/perf/EnumUtilities.Benchmark/Models/Permissions.cs new file mode 100644 index 0000000..0f02baa --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Models/Permissions.cs @@ -0,0 +1,44 @@ +using NetEscapades.EnumGenerators; +using Raiqub.Generators.EnumUtilities; + +namespace EnumUtilities.Benchmark.Models; + +[Flags] +[EnumExtensions(ExtensionClassName = "PermissionsNetEscapades")] +[EnumGenerator] +public enum Permissions : uint +{ + None = 0, + Read = 1 << 0, + Write = 1 << 1, + Execute = 1 << 2, + Delete = 1 << 3, + Modify = 1 << 4, + Create = 1 << 5, + View = 1 << 6, + Share = 1 << 7, + Copy = 1 << 8, + Move = 1 << 9, + Rename = 1 << 10, + Download = 1 << 11, + Upload = 1 << 12, + Sync = 1 << 13, + Archive = 1 << 14, + Restore = 1 << 15, + Print = 1 << 16, + Preview = 1 << 17, + Search = 1 << 18, + Tag = 1 << 19, + Annotate = 1 << 20, + Comment = 1 << 21, + Approve = 1 << 22, + Reject = 1 << 23, + Publish = 1 << 24, + Subscribe = 1 << 25, + Unsubscribe = 1 << 26, + Manage = 1 << 27, + Edit = 1 << 28, + Lock = 1 << 29, + Unlock = 1 << 30, + FullControl = 1u << 31 +} diff --git a/perf/EnumUtilities.Benchmark/Models/UserRole.cs b/perf/EnumUtilities.Benchmark/Models/UserRole.cs new file mode 100644 index 0000000..81e9c90 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Models/UserRole.cs @@ -0,0 +1,17 @@ +using NetEscapades.EnumGenerators; +using Raiqub.Generators.EnumUtilities; + +namespace EnumUtilities.Benchmark.Models; + +[Flags] +[EnumExtensions(ExtensionClassName = "UserRoleNetEscapades")] +[EnumGenerator] +public enum UserRole +{ + None = 0, + NormalUser = 1 << 0, + Custodian = 1 << 1, + Finance = 1 << 2, + SuperUser = Custodian | Finance, + All = Custodian | Finance | NormalUser +} diff --git a/perf/EnumUtilities.Benchmark/Models/Valar.cs b/perf/EnumUtilities.Benchmark/Models/Valar.cs new file mode 100644 index 0000000..ac35f14 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Models/Valar.cs @@ -0,0 +1,18 @@ +using NetEscapades.EnumGenerators; +using Raiqub.Generators.EnumUtilities; + +namespace EnumUtilities.Benchmark.Models; + +[EnumExtensions(ExtensionClassName = "ValarNetEscapades")] +[EnumGenerator] +public enum Valar +{ + Manwe = 1, + Varda, + Ulmo, + Aule, + Yavanna, + Mandos, + Nienna, + Orome, +} diff --git a/perf/EnumUtilities.Benchmark/Program.cs b/perf/EnumUtilities.Benchmark/Program.cs new file mode 100644 index 0000000..4fd5cd4 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Program.cs @@ -0,0 +1,7 @@ +using System.Reflection; +using BenchmarkDotNet.Running; +using EnumUtilities.Benchmark.Config; + +BenchmarkSwitcher + .FromAssembly(Assembly.GetCallingAssembly()) + .Run(args, new BenchmarkConfig()); diff --git a/perf/EnumUtilities.Benchmark/Tests/BigEnumParse.cs b/perf/EnumUtilities.Benchmark/Tests/BigEnumParse.cs new file mode 100644 index 0000000..a9551b8 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/BigEnumParse.cs @@ -0,0 +1,33 @@ +using BenchmarkDotNet.Attributes; +using EnumsNET; +using EnumUtilities.Benchmark.Models; +using FastEnumUtility; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class BigEnumParse +{ + public IEnumerable Values => + [ + "0", "Galadriel", "Aredhel", "1000", + ]; + + [ParamsSource(nameof(Values))] public string Elf = string.Empty; + + [Benchmark(Baseline = true)] + public Elf BuiltInParse() => Enum.Parse(Elf); + + [Benchmark] + public Elf FastEnumParse() => FastEnum.Parse(Elf); + + [Benchmark] + public Elf EnumsNetParse() => Enums.Parse(Elf); + + [Benchmark] + public Elf NetEscapadesParse() => ElfNetEscapades.Parse(Elf); + + [Benchmark] + public Elf RaiqubParse() => ElfFactory.Parse(Elf); +} diff --git a/perf/EnumUtilities.Benchmark/Tests/BigEnumToString.cs b/perf/EnumUtilities.Benchmark/Tests/BigEnumToString.cs new file mode 100644 index 0000000..eca4514 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/BigEnumToString.cs @@ -0,0 +1,33 @@ +using BenchmarkDotNet.Attributes; +using EnumsNET; +using EnumUtilities.Benchmark.Models; +using FastEnumUtility; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class BigEnumToString +{ + public IEnumerable Values => + [ + 0, (Elf)1, (Elf)32, (Elf)1000 + ]; + + [ParamsSource(nameof(Values))] public Elf Elf; + + [Benchmark(Baseline = true)] + public string BuiltInToString() => Elf.ToString(); + + [Benchmark] + public string FastEnumToString() => Elf.FastToString(); + + [Benchmark] + public string EnumsNetAsString() => Elf.AsString(); + + [Benchmark] + public string NetEscapadesToString() => ElfNetEscapades.ToStringFast(Elf); + + [Benchmark] + public string RaiqubToString() => ElfExtensions.ToStringFast(Elf); +} diff --git a/perf/EnumUtilities.Benchmark/Tests/BigFlagsEnumParse.cs b/perf/EnumUtilities.Benchmark/Tests/BigFlagsEnumParse.cs new file mode 100644 index 0000000..8e14a72 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/BigFlagsEnumParse.cs @@ -0,0 +1,36 @@ +using BenchmarkDotNet.Attributes; +using EnumsNET; +using EnumUtilities.Benchmark.Models; +using FastEnumUtility; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class BigFlagsEnumParse +{ + public IEnumerable Values => + [ + "0", "Restore", "Read, Write", "Delete, Create, View, Share, Copy, Move", + "Read, Write, Execute, Delete, Modify, Create, View, Share, Copy, Move, Rename, Download, Upload, Sync, " + + "Archive, Restore, Print, Preview, Search, Tag, Annotate, Comment, Approve, Reject, Publish, Subscribe, " + + "Unsubscribe, Manage, Edit, Lock, Unlock", + ]; + + [ParamsSource(nameof(Values))] public string Permissions = string.Empty; + + [Benchmark(Baseline = true)] + public Permissions BuiltInParse() => Enum.Parse(Permissions); + + [Benchmark] + public Permissions FastEnumParse() => FastEnum.Parse(Permissions); + + [Benchmark] + public Permissions EnumsNetParse() => Enums.Parse(Permissions); + + [Benchmark] + public Permissions NetEscapadesParse() => PermissionsNetEscapades.Parse(Permissions); + + [Benchmark] + public Permissions RaiqubParse() => PermissionsFactory.Parse(Permissions); +} diff --git a/perf/EnumUtilities.Benchmark/Tests/BigFlagsEnumToString.cs b/perf/EnumUtilities.Benchmark/Tests/BigFlagsEnumToString.cs new file mode 100644 index 0000000..3ad776a --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/BigFlagsEnumToString.cs @@ -0,0 +1,33 @@ +using BenchmarkDotNet.Attributes; +using EnumsNET; +using EnumUtilities.Benchmark.Models; +using FastEnumUtility; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class BigFlagsEnumToString +{ + public IEnumerable Values => + [ + 0, (Permissions)(1 << 15), (Permissions)3, (Permissions)1000, (Permissions)int.MaxValue, + ]; + + [ParamsSource(nameof(Values))] public Permissions Permissions; + + [Benchmark(Baseline = true)] + public string BuiltInToString() => Permissions.ToString(); + + [Benchmark] + public string FastEnumToString() => Permissions.FastToString(); + + [Benchmark] + public string EnumsNetAsString() => Permissions.AsString(); + + [Benchmark] + public string NetEscapadesToString() => PermissionsNetEscapades.ToStringFast(Permissions); + + [Benchmark] + public string RaiqubToString() => PermissionsExtensions.ToStringFast(Permissions); +} diff --git a/perf/EnumUtilities.Benchmark/Tests/SmallEnumParse.cs b/perf/EnumUtilities.Benchmark/Tests/SmallEnumParse.cs new file mode 100644 index 0000000..2e76107 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/SmallEnumParse.cs @@ -0,0 +1,33 @@ +using BenchmarkDotNet.Attributes; +using EnumsNET; +using EnumUtilities.Benchmark.Models; +using FastEnumUtility; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class SmallEnumParse +{ + public IEnumerable Values => + [ + "0", "Manwe", "Orome", "1000", + ]; + + [ParamsSource(nameof(Values))] public string Valar = string.Empty; + + [Benchmark(Baseline = true)] + public Valar BuiltInParse() => Enum.Parse(Valar); + + [Benchmark] + public Valar FastEnumParse() => FastEnum.Parse(Valar); + + [Benchmark] + public Valar EnumsNetParse() => Enums.Parse(Valar); + + [Benchmark] + public Valar NetEscapadesParse() => ValarNetEscapades.Parse(Valar); + + [Benchmark] + public Valar RaiqubParse() => ValarFactory.Parse(Valar); +} diff --git a/perf/EnumUtilities.Benchmark/Tests/SmallEnumToString.cs b/perf/EnumUtilities.Benchmark/Tests/SmallEnumToString.cs new file mode 100644 index 0000000..df3f3ca --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/SmallEnumToString.cs @@ -0,0 +1,33 @@ +using BenchmarkDotNet.Attributes; +using EnumsNET; +using EnumUtilities.Benchmark.Models; +using FastEnumUtility; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class SmallEnumToString +{ + public IEnumerable Values => + [ + 0, (Valar)1, (Valar)8, (Valar)1000, + ]; + + [ParamsSource(nameof(Values))] public Valar Valar; + + [Benchmark(Baseline = true)] + public string BuiltInToString() => Valar.ToString(); + + [Benchmark] + public string FastEnumToString() => Valar.FastToString(); + + [Benchmark] + public string EnumsNetAsString() => Valar.AsString(); + + [Benchmark] + public string NetEscapadesToString() => ValarNetEscapades.ToStringFast(Valar); + + [Benchmark] + public string RaiqubToString() => ValarExtensions.ToStringFast(Valar); +} diff --git a/perf/EnumUtilities.Benchmark/Tests/SmallFlagsEnumParse.cs b/perf/EnumUtilities.Benchmark/Tests/SmallFlagsEnumParse.cs new file mode 100644 index 0000000..300f1c8 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/SmallFlagsEnumParse.cs @@ -0,0 +1,33 @@ +using BenchmarkDotNet.Attributes; +using EnumsNET; +using EnumUtilities.Benchmark.Models; +using FastEnumUtility; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class SmallFlagsEnumParse +{ + public IEnumerable Values => + [ + "0", "Finance", "NormalUser, Custodian", "1000", + ]; + + [ParamsSource(nameof(Values))] public string UserRole = string.Empty; + + [Benchmark(Baseline = true)] + public UserRole BuiltInParse() => Enum.Parse(UserRole); + + [Benchmark] + public UserRole FastEnumParse() => FastEnum.Parse(UserRole); + + [Benchmark] + public UserRole EnumsNetParse() => Enums.Parse(UserRole); + + [Benchmark] + public UserRole NetEscapadesParse() => UserRoleNetEscapades.Parse(UserRole); + + [Benchmark] + public UserRole RaiqubParse() => UserRoleFactory.Parse(UserRole); +} diff --git a/perf/EnumUtilities.Benchmark/Tests/SmallFlagsEnumToString.cs b/perf/EnumUtilities.Benchmark/Tests/SmallFlagsEnumToString.cs new file mode 100644 index 0000000..b9b7486 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/SmallFlagsEnumToString.cs @@ -0,0 +1,33 @@ +using BenchmarkDotNet.Attributes; +using EnumsNET; +using EnumUtilities.Benchmark.Models; +using FastEnumUtility; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class SmallFlagsEnumToString +{ + public IEnumerable Values => + [ + 0, (UserRole)4, (UserRole)3, (UserRole)1000, + ]; + + [ParamsSource(nameof(Values))] public UserRole UserRole; + + [Benchmark(Baseline = true)] + public string BuiltInToString() => UserRole.ToString(); + + [Benchmark] + public string FastEnumToString() => UserRole.FastToString(); + + [Benchmark] + public string EnumsNetAsString() => UserRole.AsString(); + + [Benchmark] + public string NetEscapadesToString() => UserRoleNetEscapades.ToStringFast(UserRole); + + [Benchmark] + public string RaiqubToString() => UserRoleExtensions.ToStringFast(UserRole); +} diff --git a/perf/EnumUtilities.Benchmark/Tests/SpanAndStringComparison.cs b/perf/EnumUtilities.Benchmark/Tests/SpanAndStringComparison.cs new file mode 100644 index 0000000..3b718db --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/SpanAndStringComparison.cs @@ -0,0 +1,22 @@ +using BenchmarkDotNet.Attributes; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class SpanAndStringComparison +{ + public static ReadOnlySpan Value => "FullControl"; + + [Benchmark] + public bool WithSequenceEqual() => Value.SequenceEqual("FullControl"); + + [Benchmark] + public bool WithIsExpression() => Value is "FullControl"; + + [Benchmark] + public bool WithEqualsOrdinal() => Value.Equals("FullControl", StringComparison.Ordinal); + + [Benchmark] + public bool WithEqualsOrdinalIgnoreCase() => Value.Equals("FullControl", StringComparison.OrdinalIgnoreCase); +} diff --git a/perf/EnumUtilities.Benchmark/Tests/StringCreation.cs b/perf/EnumUtilities.Benchmark/Tests/StringCreation.cs new file mode 100644 index 0000000..f9cafe7 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/Tests/StringCreation.cs @@ -0,0 +1,75 @@ +using System.Runtime.InteropServices; +using BenchmarkDotNet.Attributes; + +namespace EnumUtilities.Benchmark.Tests; + +[MemoryDiagnoser] +[MediumRunJob] +public class StringCreation +{ + private static readonly string[] s_lotrInspiredTexts = + [ + "In a land far beyond the edges of any map, where the mists of time shroud ancient secrets, a quiet village " + + "lay nestled among the rolling green hills. Here, in the quaint hamlet of Greenvale, the folk lived simply, " + + "tending to their fields and flocks, and whispering tales of the great heroes of old. By the hearth, stories " + + "of Elven lords and Dwarven kings were recited, passed down through countless generations, each tale weaving " + + "into the fabric of their humble lives. But in the dark corners of the forest, a shadow was stirring, and the " + + "wind carried with it a faint whisper, a name long forgotten. And so began a journey that would change the " + + "fate of all who dwelled in that peaceful land.", + + "The great mountains loomed on the horizon like titanic sentinels, their snow-capped peaks piercing the " + + "heavens. At their feet, the ancient forests spread like a sea of emerald, broken only by the silver thread " + + "of a mighty river winding its way through the valley. The travelers, weary from their long trek, paused for " + + "a moment, gazing up at the towering cliffs that seemed to reach up and grasp the very stars themselves. The " + + "air was cool, filled with the scent of pine and earth, and the distant cry of an eagle echoed through the " + + "crisp, clear sky. They knew that beyond these mountains lay both danger and destiny, waiting for those bold " + + "enough to seek it.", + + "In the deep of night, under the gaze of a thousand distant stars, the company made their camp by a quiet " + + "stream that murmured softly through the undergrowth. The fire crackled warmly, casting flickering shadows " + + "on the moss-covered stones, and the scent of woodsmoke drifted lazily into the cool night air. They spoke " + + "little, each lost in their own thoughts, contemplating the path that lay before them. Yet, even in the " + + "quiet of that moment, there was an unspoken understanding among them — a bond forged not by words, but by " + + "the shared trials they had endured and the hope that still burned brightly in their hearts. For they knew " + + "that the dawn would bring new challenges, and the road ahead was long and uncertain.", + ]; + + [Benchmark] + public string UninitializedString() => string.Create(100, 0, static (_, _) => { }); + + [Benchmark] + public string ZeroedString() => new string('\0', 100); + + [Benchmark] + public string MemoryMarshalReference() + { + int strlen = s_lotrInspiredTexts.Sum(x => x.Length); + var result = string.Create(strlen, 0, static (_, _) => { }); + var span = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(result.AsSpan()), strlen); + foreach (string text in s_lotrInspiredTexts) + { + text.AsSpan().CopyTo(span); + span = span.Slice(text.Length); + } + + return result; + } + + [Benchmark] + public unsafe string UnsafePointer() + { + int strlen = s_lotrInspiredTexts.Sum(x => x.Length); + var result = string.Create(strlen, 0, static (_, _) => { }); + fixed (char* ptr = result) + { + var span = new Span(ptr, strlen); + foreach (string text in s_lotrInspiredTexts) + { + text.AsSpan().CopyTo(span); + span = span.Slice(text.Length); + } + } + + return result; + } +} diff --git a/perf/EnumUtilities.Benchmark/packages.lock.json b/perf/EnumUtilities.Benchmark/packages.lock.json new file mode 100644 index 0000000..4275604 --- /dev/null +++ b/perf/EnumUtilities.Benchmark/packages.lock.json @@ -0,0 +1,288 @@ +{ + "version": 1, + "dependencies": { + "net8.0": { + "BenchmarkDotNet": { + "type": "Direct", + "requested": "[0.14.0, )", + "resolved": "0.14.0", + "contentHash": "eIPSDKi3oni734M1rt/XJAwGQQOIf9gLjRRKKJ0HuVy3vYd7gnmAIX1bTjzI9ZbAY/nPddgqqgM/TeBYitMCIg==", + "dependencies": { + "BenchmarkDotNet.Annotations": "0.14.0", + "CommandLineParser": "2.9.1", + "Gee.External.Capstone": "2.3.0", + "Iced": "1.17.0", + "Microsoft.CodeAnalysis.CSharp": "4.1.0", + "Microsoft.Diagnostics.Runtime": "2.2.332302", + "Microsoft.Diagnostics.Tracing.TraceEvent": "3.1.8", + "Microsoft.DotNet.PlatformAbstractions": "3.1.6", + "Perfolizer": "[0.3.17]", + "System.Management": "5.0.0" + } + }, + "DotNet.ReproducibleBuilds": { + "type": "Direct", + "requested": "[1.2.4, )", + "resolved": "1.2.4", + "contentHash": "Ch9U74tQA2fQH+U0hcYH7WyIFUfAq7jrjgSHVu2FAcYiMBtbrCMyq2nGA/ZZnB2jSaUeOOYiCjxeaDVB7Ssbdw==" + }, + "Enums.NET": { + "type": "Direct", + "requested": "[5.0.0, )", + "resolved": "5.0.0", + "contentHash": "NfGq1iLJZ15XZPgBhjk4Ns1XZ+beaGk6cog6B4LxcROdGoSMdgCJqYXF70P6VTd3dz/vFRY4h1u1lAMqW/DC2w==" + }, + "FastEnum": { + "type": "Direct", + "requested": "[1.8.0, )", + "resolved": "1.8.0", + "contentHash": "cBVeGWLPPHyrVcJKpANXtw0CbVyb1Ltr7Lqc/HE/WktAgxKpVD3mFMbLT4IAa5cuM5oKv2zPt6ovT7AhZf4zsg==" + }, + "Nerdbank.GitVersioning": { + "type": "Direct", + "requested": "[3.6.139, )", + "resolved": "3.6.139", + "contentHash": "rq0Ub/Jik7PtMtZtLn0tHuJ01Yt36RQ+eeBe+S7qnJ/EFOX6D4T9zuYD3vQPYKGI6Ro4t2iWgFm3fGDgjBrMfg==" + }, + "NetEscapades.EnumGenerators": { + "type": "Direct", + "requested": "[1.0.0-beta09, )", + "resolved": "1.0.0-beta09", + "contentHash": "HD7y2pNBOw0bhBBs/hnFJJP2fg4b+qTWLvyfqIZTIoZ1Ha1VC2J8PinTSz8jr8o3kxxuF36Cx1t4WOwCZkO76w==" + }, + "BenchmarkDotNet.Annotations": { + "type": "Transitive", + "resolved": "0.14.0", + "contentHash": "CUDCg6bgHrDzhjnA+IOBl5gAo8Y5hZ2YSs7MBXrYMlMKpBZqrD5ez0537uDveOkcf+YWAoK+S4sMcuWPbIz8bw==" + }, + "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.17.0", + "contentHash": "8x+HCVTl/HHTGpscH3vMBhV8sknN/muZFw9s3TsI8SA6+c43cOTCi2+jE4KsU8pNLbJ++iF2ZFcpcXHXtDglnw==" + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "3.3.3", + "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "bNzTyxP3iD5FPFHfVDl15Y6/wSoI7e3MeV0lOaj9igbIKTjgrmuw6LoVJ06jUNFA7+KaDC/OIsStWl/FQJz6sQ==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "5.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "5.0.0", + "System.Text.Encoding.CodePages": "4.5.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "sbu6kDGzo9bfQxuqWpeEE7I9P30bSuZEnpDz9/qz20OU6pm79Z63+/BsAzO2e/R/Q97kBrpj647wokZnEVr97w==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[4.1.0]" + } + }, + "Microsoft.Diagnostics.NETCore.Client": { + "type": "Transitive", + "resolved": "0.2.251802", + "contentHash": "bqnYl6AdSeboeN4v25hSukK6Odm6/54E3Y2B8rBvgqvAW0mF8fo7XNRVE2DMOG7Rk0fiuA079QIH28+V+W1Zdg==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.0", + "Microsoft.Extensions.Logging": "2.1.1" + } + }, + "Microsoft.Diagnostics.Runtime": { + "type": "Transitive", + "resolved": "2.2.332302", + "contentHash": "Hp84ivxSKIMTBzYSATxmUsm3YSXHWivcwiRRbsydGmqujMUK8BAueLN0ssAVEOkOBmh0vjUBhrq7YcroT7VCug==", + "dependencies": { + "Microsoft.Diagnostics.NETCore.Client": "0.2.251802", + "System.Collections.Immutable": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "5.0.0" + } + }, + "Microsoft.Diagnostics.Tracing.TraceEvent": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "kl3UMrZKSeSEYZ8rt/GjLUQToREjgQABqfg6PzQBmSlYHTZOKE9ePEOS2xptROQ9SVvngg3QGX51TIT11iZ0wA==", + "dependencies": { + "Microsoft.Win32.Registry": "4.4.0", + "System.Runtime.CompilerServices.Unsafe": "5.0.0" + } + }, + "Microsoft.DotNet.PlatformAbstractions": { + "type": "Transitive", + "resolved": "3.1.6", + "contentHash": "jek4XYaQ/PGUwDKKhwR8K47Uh1189PFzMeLqO83mXrXQVIpARZCcfuDedH50YDTepBkfijCZN5U/vZi++erxtg==" + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "LjVKO6P2y52c5ZhTLX/w8zc5H4Y3J/LJsgqTBj49TtFq/hAtVNue/WA0F6/7GMY90xhD7K0MDZ4qpOeWXbLvzg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.1.1" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "VfuZJNa0WUshZ/+8BFZAhwFKiKuu/qOUCFntfdLpHj7vcRnsGHqd3G2Hse78DM+pgozczGM63lGPRLmy+uhUOA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.1" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "fcLCTS03poWE4v9tSNBr3pWn0QwGgAn1vzqHXlXgvqZeOc7LvQNzaWcKRQZTdEc3+YhQKwMsOtm3VKSA2aWQ8w==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.1.1" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "MgYpU5cwZohUMKKg3sbPhvGG+eAZ/59E9UwPwlrUkyXU+PGzqwZg9yyQNjhxuAWmoNoFReoemeCku50prYSGzA==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "hh+mkOAQDTp6XH80xJt3+wwYVzkbwYQl9XZRCz4Um0JjP/o7N9vHM3rZ6wwwtr+BBe/L6iBO2sz0px6OWBzqZQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "2.1.1", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "Microsoft.Extensions.Options": "2.1.1" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "XRzK7ZF+O6FzdfWrlFTi1Rgj2080ZDsd46vzOjadHUB0Cz5kOvDG8vI7caa5YFrsHQpcfn0DxtjS4E46N4FZsA==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "V7lXCU78lAbzaulCGFKojcCyG8RTJicEbiBkPJjFqiqXwndEBBIehdXRMWEVU3UtzQ1yDvphiWUL9th6/4gJ7w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Primitives": "2.1.1" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg==", + "dependencies": { + "System.Memory": "4.5.1", + "System.Runtime.CompilerServices.Unsafe": "4.5.1" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Perfolizer": { + "type": "Transitive", + "resolved": "0.3.17", + "contentHash": "FQgtCoF2HFwvzKWulAwBS5BGLlh8pgbrJtOp47jyBwh2CW16juVtacN1azOA2BqdrJXkXTNLNRMo7ZlHHiuAnA==" + }, + "System.CodeDom": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "JPJArwA1kdj8qDAkY2XGjSWoYnqiM7q/3yRNkt6n28Mnn95MuEGkZXUbPBf7qc3IjwrGY5ttQon7yqHZyQJmOQ==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" + }, + "System.Management": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "MF1CHaRcC+MLFdnDthv4/bKWBZnlnSpkGqa87pKukQefgEdwtb9zFW6zs0GjPp73qtpYYg4q6PEKbzJbxCpKfw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.CodeDom": "5.0.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA==" + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "dependencies": { + "Microsoft.NETCore.Platforms": "2.1.2", + "System.Runtime.CompilerServices.Unsafe": "4.5.2" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "Raiqub.Generators.EnumUtilities": { + "type": "Project" + } + } + } +} \ No newline at end of file diff --git a/src/EnumUtilities/Formatters/EnumStringFormatter.cs b/src/EnumUtilities/Formatters/EnumStringFormatter.cs index 23a4ccf..fd91b8d 100644 --- a/src/EnumUtilities/Formatters/EnumStringFormatter.cs +++ b/src/EnumUtilities/Formatters/EnumStringFormatter.cs @@ -1,79 +1,54 @@ -namespace Raiqub.Generators.EnumUtilities.Formatters; +using System.Runtime.InteropServices; + +namespace Raiqub.Generators.EnumUtilities.Formatters; /// Provides utility methods for formatting enumerations as strings. public static class EnumStringFormatter { - /// Gets the number of characters required to represent the given value using the specified formatter. - /// The type of the formatter. - /// The type of the number. - /// The value to format. - /// The formatter to use. - /// The length of the string representation of the value. - public static int GetStringLength( - TNumber value, - TFormatter enumFormatter) - where TFormatter : IEnumFormatter - where TNumber : struct - { - return enumFormatter.TryGetStringLengthForMember(value) ?? enumFormatter.GetStringLengthForNumber(value); - } - - /// Gets the string representation of the given value using the specified formatter. - /// The type of the formatter. - /// The type of the number. - /// The value to format. - /// The formatter to use. - /// The string representation of the value. - public static string GetString( - TNumber value, - TFormatter enumFormatter) - where TFormatter : IEnumFormatter - where TNumber : struct - { - return enumFormatter.TryGetStringForMember(value) ?? enumFormatter.GetStringForNumber(value); - } - /// /// Writes the names of multiple found flags into a single string, separated by commas. /// - /// The type of the formatter used to get string representations of the flags. - /// The underlying type of the enumeration values. - /// The formatter used to convert enum values to their string representations. - /// The total length of the resulting string, excluding separators. + /// A span containing all enumeration names. + /// A span containing the string of found enum values. /// The number of enum values found. - /// A span containing the found enum values. + /// The total length of the resulting string, excluding separators. /// A string that represents the names of the found flags, separated by commas. /// Thrown if the computed string length exceeds the capacity of an . - public static string WriteMultipleFoundFlagsNames( - TFormatter enumFormatter, - int count, + public static unsafe string WriteMultipleFoundFlagsNames( + ReadOnlySpan names, + Span foundItems, int foundItemsCount, - Span foundItems) - where TFormatter : IEnumFlagsFormatter - where TNumber : struct + int count) { const int separatorStringLength = 2; - const char enumSeparatorChar = ','; int strlen = checked(count + (separatorStringLength * (foundItemsCount - 1))); - Span result = strlen <= 128 - ? stackalloc char[128].Slice(0, strlen) - : new char[strlen]; - var span = result; - string name = enumFormatter.GetStringForSingleMember(foundItems[--foundItemsCount]); - name.AsSpan().CopyTo(span); - span = span.Slice(name.Length); - while (--foundItemsCount >= 0) +#if NET6_0_OR_GREATER + var result = string.Create(strlen, 0, static (_, _) => { }); + var span = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(result.AsSpan()), strlen); { - span[0] = enumSeparatorChar; - span[1] = ' '; - span = span.Slice(2); +#else + var result = new string('\0', strlen); + fixed (char* ptr = result) + { + var span = new Span(ptr, strlen); +#endif - name = enumFormatter.GetStringForSingleMember(foundItems[foundItemsCount]); + string name = names[foundItems[--foundItemsCount]]; name.AsSpan().CopyTo(span); span = span.Slice(name.Length); + while (--foundItemsCount >= 0) + { + span[0] = ','; + span[1] = ' '; + span = span.Slice(2); + + name = names[foundItems[foundItemsCount]]; + name.AsSpan().CopyTo(span); + span = span.Slice(name.Length); + } } - return result.ToString(); + return result; } } diff --git a/src/EnumUtilities/Formatters/IEnumFlagsFormatter.cs b/src/EnumUtilities/Formatters/IEnumFlagsFormatter.cs deleted file mode 100644 index 6e4702a..0000000 --- a/src/EnumUtilities/Formatters/IEnumFlagsFormatter.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Raiqub.Generators.EnumUtilities.Formatters; - -/// Represents an interface for formatting enum values that are flags. -/// The underlying type of the enum. -public interface IEnumFlagsFormatter : IEnumFormatter -{ - /// Gets the string representation of a single member in a flags enumeration. - /// The enumeration value representing a single flag. - /// The string representation of the single flag, or null if the value does not correspond to a valid flag. - string GetStringForSingleMember(T value); -} diff --git a/src/EnumUtilities/Formatters/IEnumFormatter.cs b/src/EnumUtilities/Formatters/IEnumFormatter.cs deleted file mode 100644 index ae12911..0000000 --- a/src/EnumUtilities/Formatters/IEnumFormatter.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace Raiqub.Generators.EnumUtilities.Formatters; - -/// Represents a generic interface for formatting enum values. -/// The underlying type of enum. -public interface IEnumFormatter -{ - /// Gets the number of characters required to represent the given enumeration value as a number. - /// The enumeration value. - /// The length of the string representation of the value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - int GetStringLengthForNumber(T value); - - /// Gets the string representation of the given enumeration value as a number. - /// The enumeration value. - /// The string representation of the value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - string GetStringForNumber(T value); - - /// Attempts to get the number of characters required to represent the given enumeration member. - /// The enumeration value. - /// The length of the string representation of the value, or null if the value could not be converted. - int? TryGetStringLengthForMember(T value); - - /// Attempts to get the string representation of the given enumeration member. - /// The enumeration value. - /// The string representation of the value, or null if the value could not be converted. - string? TryGetStringForMember(T value); -} diff --git a/src/EnumUtilities/JsonConverterGeneratorAttribute.cs b/src/EnumUtilities/JsonConverterGeneratorAttribute.cs index b88173a..558c967 100644 --- a/src/EnumUtilities/JsonConverterGeneratorAttribute.cs +++ b/src/EnumUtilities/JsonConverterGeneratorAttribute.cs @@ -2,10 +2,25 @@ namespace Raiqub.Generators.EnumUtilities; +/// +/// An attribute used by the code generator to specify options for generating a JSON converter for the enumeration. +/// [AttributeUsage(AttributeTargets.Enum)] [ExcludeFromCodeCoverage] public sealed class JsonConverterGeneratorAttribute : Attribute { + /// + /// Gets or sets a value indicating whether integer values are allowed during deserialization. The default is true. + /// public bool AllowIntegerValues { get; set; } = true; + + /// + /// Gets or sets a value indicating whether case should be ignored during deserialization. The default is false. + /// + public bool IgnoreCase { get; set; } + + /// + /// Gets or sets the fallback value to use when deserialization fails. + /// public object? DeserializationFailureFallbackValue { get; set; } } diff --git a/src/EnumUtilities/Parsers/EnumStringParser.cs b/src/EnumUtilities/Parsers/EnumStringParser.cs deleted file mode 100644 index 3ddd8e5..0000000 --- a/src/EnumUtilities/Parsers/EnumStringParser.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace Raiqub.Generators.EnumUtilities.Parsers; - -/// Provides utility methods for parsing enum values from string representations. -[EditorBrowsable(EditorBrowsableState.Never)] -public static class EnumStringParser -{ - /// Tries to parse an enum value from a string representation. - /// The type of the enum parser. - /// The underlying numeric type of the enum. - /// The string representation to parse. - /// An instance of the enum parser. - /// One of the enumeration values that specifies how the strings will be compared. - /// Indicates whether an exception should be thrown on parsing failure. - /// When this method returns, contains the parsed enum value if successful; otherwise, the default value. - /// true if the parsing was successful; otherwise, false. - public static bool TryParse( - ReadOnlySpan value, - TParser enumParser, - StringComparison comparisonType, - bool throwOnFailure, - out TNumber result) - where TParser : IEnumParser - where TNumber : struct - { - switch (AnalyseForParsing(value, out value)) - { - case ParseAnalysisResult.NotNumeric: - return TryParseByName(value, enumParser, comparisonType, throwOnFailure, out result); - case ParseAnalysisResult.MaybeNumeric: - return enumParser.TryParseNumber(value, out result) || - TryParseByName(value, enumParser, comparisonType, throwOnFailure, out result); - case ParseAnalysisResult.Empty: - default: - return TryParseEmpty(value, enumParser, comparisonType, nameof(value), throwOnFailure, out result); - } - } - - public static bool TryParseDescription( - ReadOnlySpan description, - TParser parser, - StringComparison comparisonType, - bool throwOnFailure, - out TNumber result) - where TParser : IEnumDescriptionParser - where TNumber : struct - { - if (description.IsWhiteSpace()) - { - return TryParseEmpty(nameof(description), throwOnFailure, out result); - } - - bool success = parser.TryParseDescription(description, comparisonType, out result); - if (success) - { - return true; - } - - if (throwOnFailure) - { - ThrowValueNotFound(description, nameof(description)); - } - - return false; - } - - private static bool TryParseByName( - ReadOnlySpan value, - TParser enumParser, - StringComparison comparisonType, - bool throwOnFailure, - out TNumber result) - where TParser : IEnumParser - where TNumber : struct - { - bool parsed = true; - TNumber localResult = default; - foreach (var item in new FlagsEnumTokenizer(value)) - { - bool success = enumParser.TryParseSingleName(item, comparisonType, out TNumber singleValue); - if (!success) - { - parsed = false; - break; - } - - localResult = enumParser.BitwiseOr(localResult, singleValue); - } - - if (parsed) - { - result = localResult; - return true; - } - - if (throwOnFailure) - { - ThrowValueNotFound(value, nameof(value)); - } - - result = default; - return false; - } - - private static bool TryParseEmpty( - ReadOnlySpan value, - TParser enumParser, - StringComparison comparisonType, - string parameterName, - bool throwOnFailure, - out TNumber result) - where TParser : IEnumParser - where TNumber : struct - { - if (enumParser.TryParseSingleName(value, comparisonType, out result)) - { - return true; - } - - if (throwOnFailure) - { - ThrowInvalidEmptyParseArgument(parameterName); - } - - return false; - } - - private static bool TryParseEmpty(string parameterName, bool throwOnFailure, out TNumber result) - where TNumber : struct - { - if (throwOnFailure) - { - ThrowInvalidEmptyParseArgument(parameterName); - } - - result = default; - return false; - } - - private enum ParseAnalysisResult - { - Empty, - NotNumeric, - MaybeNumeric - } - - private static ParseAnalysisResult AnalyseForParsing(ReadOnlySpan value, out ReadOnlySpan result) - { - if (value.IsEmpty) - { - result = default; - return ParseAnalysisResult.Empty; - } - - char c = value[0]; - if (char.IsWhiteSpace(c)) - { - value = value.TrimStart(); - if (value.IsEmpty) - { - result = default; - return ParseAnalysisResult.Empty; - } - - c = value[0]; - } - - result = value; - return IsAsciiDigit(c) || c == '-' || c == '+' - ? ParseAnalysisResult.MaybeNumeric - : ParseAnalysisResult.NotNumeric; - } - - private static void ThrowInvalidEmptyParseArgument(string parameterName) - { - throw new ArgumentException( - "Must specify valid information for parsing in the string.", - parameterName); - } - - private static void ThrowValueNotFound(ReadOnlySpan value, string parameterName) - { -#if !NETSTANDARD2_0 - throw new ArgumentException($"Requested value '{value}' was not found.", parameterName); -#else - throw new ArgumentException($"Requested value '{value.ToString()}' was not found.", parameterName); -#endif - } - - /// Indicates whether a character is categorized as an ASCII digit. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsAsciiDigit(char c) => c is >= '0' and <= '9'; -} diff --git a/src/EnumUtilities/Parsers/FlagsEnumTokenizer.cs b/src/EnumUtilities/Parsers/FlagsEnumTokenizer.cs index 2a9c1fe..4ce544b 100644 --- a/src/EnumUtilities/Parsers/FlagsEnumTokenizer.cs +++ b/src/EnumUtilities/Parsers/FlagsEnumTokenizer.cs @@ -7,7 +7,7 @@ namespace Raiqub.Generators.EnumUtilities.Parsers; /// A that tokenizes a given span of characters for bit flags enum. /// [EditorBrowsable(EditorBrowsableState.Never)] -internal ref struct FlagsEnumTokenizer +public ref struct FlagsEnumTokenizer { /// Character used to separate flag enum values when formatted in a list. private const char EnumSeparatorChar = ','; diff --git a/src/EnumUtilities/Parsers/IEnumDescriptionParser.cs b/src/EnumUtilities/Parsers/IEnumDescriptionParser.cs deleted file mode 100644 index 52a2fe9..0000000 --- a/src/EnumUtilities/Parsers/IEnumDescriptionParser.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Raiqub.Generators.EnumUtilities.Parsers; - -public interface IEnumDescriptionParser -{ - bool TryParseDescription(ReadOnlySpan value, StringComparison comparisonType, out T result); -} diff --git a/src/EnumUtilities/Parsers/IEnumParser.cs b/src/EnumUtilities/Parsers/IEnumParser.cs deleted file mode 100644 index 0cebd52..0000000 --- a/src/EnumUtilities/Parsers/IEnumParser.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace Raiqub.Generators.EnumUtilities.Parsers; - -/// Represents a generic interface for parsing and manipulating enum values. -/// The underlying type of enum. -public interface IEnumParser -{ - /// Computes the bitwise OR of two enum values. - /// The first enum value. - /// The second enum value. - /// The result of the bitwise OR operation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - T BitwiseOr(T value1, T value2); - - /// Tries to parse an enum value from a numeric representation. - /// The numeric representation as a character span. - /// When this method returns, contains the parsed enum value if successful; otherwise, the default value. - /// true if the parsing was successful; otherwise, false. - bool TryParseNumber(ReadOnlySpan value, out T result); - - /// Tries to parse an enum value from a single name. - /// The name of the enum value as a character span. - /// One of the enumeration values that specifies how the strings will be compared. - /// When this method returns, contains the parsed enum value if successful; otherwise, the default value. - /// true if the parsing was successful; otherwise, false. - bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out T result); -} diff --git a/src/EnumUtilities/Parsers/ThrowHelper.cs b/src/EnumUtilities/Parsers/ThrowHelper.cs new file mode 100644 index 0000000..56f9112 --- /dev/null +++ b/src/EnumUtilities/Parsers/ThrowHelper.cs @@ -0,0 +1,59 @@ +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace Raiqub.Generators.EnumUtilities.Parsers; + +/// +/// Provides helper methods to throw exceptions with standardized messages. +/// +#if NET6_0_OR_GREATER +[StackTraceHidden] +#endif +public static class ThrowHelper +{ + /// + /// Throws an indicating that an empty value was provided for a parsing operation. + /// + /// The name of the parameter that caused the exception. + /// Thrown to indicate that the provided argument is invalid for parsing. +#if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + [DoesNotReturn] +#endif + public static void ThrowInvalidEmptyParseArgument(string parameterName) + { + throw new ArgumentException( + "Must specify valid information for parsing in the string.", + parameterName); + } + + /// + /// Throws an indicating that a requested value was not found. + /// + /// The value that was not found. + /// The name of the parameter that caused the exception. + /// Thrown to indicate that the requested value was not found. +#if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + [DoesNotReturn] +#endif + public static void ThrowValueNotFound(ReadOnlySpan value, string parameterName) + { +#if !NETSTANDARD2_0 + throw new ArgumentException($"Requested value '{value}' was not found.", parameterName); +#else + throw new ArgumentException($"Requested value '{value.ToString()}' was not found.", parameterName); +#endif + } + + /// + /// Throws an indicating that a required argument is . + /// + /// The name of the parameter that is . + /// Always thrown to indicate that the specified parameter is . +#if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + [DoesNotReturn] +#endif + public static void ThrowArgumentNullException(string paramName) + { + throw new ArgumentNullException(paramName); + } +} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/EnumFactoryTests.cs b/tests/EnumUtilities.Generators.IntegrationTests/EnumFactoryTests.cs index 7f648c1..61f45d1 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/EnumFactoryTests.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/EnumFactoryTests.cs @@ -34,7 +34,6 @@ public void TryParseBitFlagsIsSameAsEnumParse(string value) [InlineData(nameof(Categories.Arts))] [InlineData(nameof(Categories.Fashion))] [InlineData($" {nameof(Categories.Automotive)}")] - [InlineData($"{nameof(Categories.Electronics)}, {nameof(Categories.BeautyCare)}")] [InlineData($"{nameof(Categories.BeautyCare)},")] [InlineData($"{nameof(Categories.Arts)}, ")] [InlineData("15")] diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeEnumInfo.g.cs deleted file mode 100644 index b69b37c..0000000 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeEnumInfo.g.cs +++ /dev/null @@ -1,126 +0,0 @@ -// -#nullable enable - -using System; -using System.Runtime.CompilerServices; -using Raiqub.Generators.EnumUtilities.Formatters; -using Raiqub.Generators.EnumUtilities.Parsers; - -#pragma warning disable CS1591 // publicly visible type or member must be documented - -namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models -{ - [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] - internal static partial class BigErrorCodeMetadata - { - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(ulong value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(ulong value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(ulong value) - { - return value switch - { - 0 => 4, - 1 => 7, - 100 => 14, - 200000000000 => 14, - _ => null - }; - } - - /// - public string? TryGetStringForMember(ulong value) - { - return value switch - { - 0 => "None", - 1 => "Unknown", - 100 => "ConnectionLost", - 200000000000 => "OutlierReading", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ulong BitwiseOr(ulong value1, ulong value2) => unchecked((ulong)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out ulong result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out ulong result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'N': - case 'n': - switch (value) - { - case { } when value.Equals("None", comparisonType): - result = 0; - return true; - } - goto default; - case 'U': - case 'u': - switch (value) - { - case { } when value.Equals("Unknown", comparisonType): - result = 1; - return true; - } - goto default; - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("ConnectionLost", comparisonType): - result = 100; - return true; - } - goto default; - case 'O': - case 'o': - switch (value) - { - case { } when value.Equals("OutlierReading", comparisonType): - result = 200000000000; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } - } -} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeExtensions.g.cs new file mode 100644 index 0000000..03f7f09 --- /dev/null +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeExtensions.g.cs @@ -0,0 +1,54 @@ +// +#nullable enable + +using System; +using System.Runtime.CompilerServices; +using System.Threading; +using Raiqub.Generators.EnumUtilities.Formatters; + +#pragma warning disable CS1591 // publicly visible type or member must be documented + +namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] + internal static partial class BigErrorCodeExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? ToJsonString(this BigErrorCode value) + { + return GetJsonStringInlined((ulong)value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? GetJsonStringLength(this BigErrorCode value) + { + return GetJsonStringLengthInlined((ulong)value); + } + + private static int? GetJsonStringLengthInlined(ulong value) + { + return value switch + { + 0 => 3, + 1 => 3, + 100 => 3, + 200000000000 => 3, + _ => null + }; + } + + private static string? GetJsonStringInlined(ulong value) + { + return value switch + { + 0 => "NON", + 1 => "UNK", + 100 => "CNX", + 200000000000 => "OUT", + _ => null + }; + } + } +} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeFactory.g.cs new file mode 100644 index 0000000..ace0d36 --- /dev/null +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeFactory.g.cs @@ -0,0 +1,244 @@ +// +#nullable enable + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Runtime.CompilerServices; +using Raiqub.Generators.EnumUtilities.Parsers; + +#pragma warning disable CS1591 // publicly visible type or member must be documented + +namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] + internal static partial class BigErrorCodeFactory + { + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value. Note that this value need not be a member of the BigErrorCode enumeration. + /// is . + /// is empty or does not represent a valid value. + public static BigErrorCode ParseJsonString(string value, bool ignoreCase = false) + { + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (BigErrorCode)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value. Note that this value need not be a member of the BigErrorCode enumeration. + /// is empty or does not represent a valid value. + public static BigErrorCode ParseJsonString(ReadOnlySpan value, bool ignoreCase = false) + { + TryParseJsonString(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (BigErrorCode)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value or null. Note that this value need not be a member of the BigErrorCode enumeration. + /// is empty or does not represent a valid value. + [return: NotNullIfNotNull("value")] + public static BigErrorCode? ParseJsonStringOrNull(string? value, bool ignoreCase = false) + { + if (value is null) return null; + TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (BigErrorCode)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// When this method returns, result contains an object of type BigErrorCode whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of BigErrorCode. Note that this value need not be a member of the BigErrorCode enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString([NotNullWhen(true)] string? value, bool ignoreCase, out BigErrorCode result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// + /// When this method returns, result contains an object of type BigErrorCode whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of BigErrorCode. Note that this value need not be a member of the BigErrorCode enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString([NotNullWhen(true)] string? value, out BigErrorCode result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// Contains an object of type BigErrorCode whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains a null value. + /// + public static BigErrorCode? TryParseJsonString(string? value, bool ignoreCase = false) + { + return TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (BigErrorCode?)result : null; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// When this method returns, result contains an object of type BigErrorCode whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of BigErrorCode. Note that this value need not be a member of the BigErrorCode enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString(ReadOnlySpan value, bool ignoreCase, out BigErrorCode result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// + /// When this method returns, result contains an object of type BigErrorCode whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of BigErrorCode. Note that this value need not be a member of the BigErrorCode enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString(ReadOnlySpan value, out BigErrorCode result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// Contains an object of type BigErrorCode whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains a null value. + /// + public static BigErrorCode? TryParseJsonString(ReadOnlySpan value, bool ignoreCase = false) + { + return TryParseJsonString(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (BigErrorCode?)result : null; + } + + private static bool TryParseJsonString(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out ulong result) + { + if (!value.IsEmpty) + { + return TryParseNonNumericJsonString(value, comparisonType, throwOnFailure, out result); + } + + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericJsonString(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out ulong result) + { + bool success = TryParseSingleJsonString(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; + } + + private static bool TryParseSingleJsonString(ReadOnlySpan value, StringComparison comparisonType, out ulong result) + { + if (value.IsEmpty) + { + result = 0; + return false; + } + + switch (value[0]) + { + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("CNX", comparisonType): + result = 100; + return true; + } + break; + case 'N': + case 'n': + switch (value) + { + case { } when value.Equals("NON", comparisonType): + result = 0; + return true; + } + break; + case 'O': + case 'o': + switch (value) + { + case { } when value.Equals("OUT", comparisonType): + result = 200000000000; + return true; + } + break; + case 'U': + case 'u': + switch (value) + { + case { } when value.Equals("UNK", comparisonType): + result = 1; + return true; + } + break; + } + + result = 0; + return false; + } + } +} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeJsonConverter.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeJsonConverter.g.cs index 0f78302..645e508 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeJsonConverter.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.BigErrorCodeJsonConverter.g.cs @@ -2,6 +2,7 @@ #nullable enable using System; +using System.Buffers; using System.Text.Json; using System.Text.Json.Serialization; using Raiqub.Generators.EnumUtilities.Formatters; @@ -12,104 +13,78 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal sealed class BigErrorCodeJsonConverter : JsonConverter { - private const int MaxBytesLength = 3; - private const int MaxCharsLength = 3; - - private static readonly BigErrorCodeMetadata.StringFormatter s_stringFormatter = BigErrorCodeMetadata.StringFormatter.Instance; - private static readonly BigErrorCodeMetadata.StringParser s_stringParser = BigErrorCodeMetadata.StringParser.Instance; + private const int MaxCharStack = 256; public override BigErrorCode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) - return (BigErrorCode)ReadFromString(ref reader); + return ReadFromString(ref reader); return (BigErrorCode)0; } - #if NET7_0_OR_GREATER - public override void Write(Utf8JsonWriter writer, BigErrorCode value, JsonSerializerOptions options) { - switch ((ulong)value) + string? jsonString = value.ToJsonString(); + if (jsonString is not null) + { + writer.WriteStringValue(jsonString); + } + else { - case 0: - writer.WriteStringValue("NON"u8); - break; - case 1: - writer.WriteStringValue("UNK"u8); - break; - case 100: - writer.WriteStringValue("CNX"u8); - break; - case 200000000000: - writer.WriteStringValue("OUT"u8); - break; - default: - string strValue = EnumStringFormatter.GetString((ulong)value, s_stringFormatter); - writer.WriteStringValue(strValue); - break; + jsonString = ((BigErrorCode)0).ToJsonString(); + if (jsonString is not null) + writer.WriteStringValue(jsonString); + else + throw new JsonException(); } } - private ulong ReadFromString(ref Utf8JsonReader reader) + #if NET7_0_OR_GREATER + + private BigErrorCode ReadFromString(ref Utf8JsonReader reader) { int length = reader.HasValueSequence ? checked((int)reader.ValueSequence.Length) : reader.ValueSpan.Length; - if (length > MaxBytesLength) - return 0; - Span name = stackalloc char[MaxBytesLength]; - int charsWritten = reader.CopyString(name); - name = name.Slice(0, charsWritten); - - return name switch + char[]? rented = null; + Span name = length <= MaxCharStack ? stackalloc char[MaxCharStack] : (rented = ArrayPool.Shared.Rent(length)); + try { - "NON" => 0, - "UNK" => 1, - "CNX" => 100, - "OUT" => 200000000000, - _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out ulong result) ? result : 0 - }; - } + int charsWritten = reader.CopyString(name); + name = name.Slice(0, charsWritten); - #else + bool isParsed = BigErrorCodeFactory.TryParseJsonString(name, ignoreCase: false, out BigErrorCode result); + if (!isParsed) + { + return (BigErrorCode)0; + } - public override void Write(Utf8JsonWriter writer, BigErrorCode value, JsonSerializerOptions options) - { - switch ((ulong)value) + return result; + } + finally { - case 0: - writer.WriteStringValue("NON"); - break; - case 1: - writer.WriteStringValue("UNK"); - break; - case 100: - writer.WriteStringValue("CNX"); - break; - case 200000000000: - writer.WriteStringValue("OUT"); - break; - default: - string strValue = EnumStringFormatter.GetString((ulong)value, s_stringFormatter); - writer.WriteStringValue(strValue); - break; + if (rented != null) + { + ArrayPool.Shared.Return(rented); + } } } - private ulong ReadFromString(ref Utf8JsonReader reader) + #else + + private BigErrorCode ReadFromString(ref Utf8JsonReader reader) { var name = reader.GetString(); - return name switch + bool isParsed = BigErrorCodeFactory.TryParseJsonString(name, ignoreCase: false, out BigErrorCode result); + if (!isParsed) { - "NON" => 0, - "UNK" => 1, - "CNX" => 100, - "OUT" => 200000000000, - _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out ulong result) ? result : 0 - }; + return (BigErrorCode)0; + } + + return result; } #endif diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesEnumInfo.g.cs index 5ef4dcf..7d956bc 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesEnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesEnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class CategoriesMetadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 11; /// The string representation of name. @@ -42,7 +43,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 11; /// The UTF-8 representation of name. @@ -63,124 +64,5 @@ public static partial class Utf8Name /// The UTF-8 representation of name. public static ReadOnlySpan Fashion => new byte[7] { 70, 97, 115, 104, 105, 111, 110 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 0 => 11, - 1 => 4, - 2 => 10, - 3 => 4, - 4 => 10, - 5 => 7, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 0 => "Electronics", - 1 => "Food", - 2 => "Automotive", - 3 => "Arts", - 4 => "BeautyCare", - 5 => "Fashion", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'E': - case 'e': - switch (value) - { - case { } when value.Equals("Electronics", comparisonType): - result = 0; - return true; - } - goto default; - case 'F': - case 'f': - switch (value) - { - case { } when value.Equals("Food", comparisonType): - result = 1; - return true; - case { } when value.Equals("Fashion", comparisonType): - result = 5; - return true; - } - goto default; - case 'A': - case 'a': - switch (value) - { - case { } when value.Equals("Automotive", comparisonType): - result = 2; - return true; - case { } when value.Equals("Arts", comparisonType): - result = 3; - return true; - } - goto default; - case 'B': - case 'b': - switch (value) - { - case { } when value.Equals("BeautyCare", comparisonType): - result = 4; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesExtensions.g.cs index 7dd6f4a..3a83329 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesExtensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesExtensions.g.cs @@ -11,16 +11,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class CategoriesExtensions { - private static readonly CategoriesMetadata.StringFormatter s_stringFormatter = CategoriesMetadata.StringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this Categories value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return GetNameInlined((int)value) + ?? ((int)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -28,14 +27,52 @@ public static string ToStringFast(this Categories value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this Categories value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return GetNameLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this Categories value) { - return CategoriesValidation.IsDefined(value); + return (int)value switch + { + 0 => true, + 1 => true, + 2 => true, + 3 => true, + 4 => true, + 5 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + 0 => 11, + 1 => 4, + 2 => 10, + 3 => 4, + 4 => 10, + 5 => 7, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + 0 => "Electronics", + 1 => "Food", + 2 => "Automotive", + 3 => "Arts", + 4 => "BeautyCare", + 5 => "Fashion", + _ => null + }; } /// Adds two enumerations and replaces the first integer with the sum, as an atomic operation. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesFactory.g.cs index 2877bfd..4cba4ab 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesFactory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesFactory.g.cs @@ -12,11 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class CategoriesFactory { - private static readonly CategoriesMetadata.StringParser s_stringParser = CategoriesMetadata.StringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -28,9 +26,9 @@ public static partial class CategoriesFactory /// is empty or does not represent a valid value. public static Categories Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (Categories)result; } /// @@ -43,8 +41,8 @@ public static Categories Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static Categories Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (Categories)result; } /// @@ -59,8 +57,8 @@ public static Categories Parse(ReadOnlySpan value, bool ignoreCase = false public static Categories? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (Categories)result; } /// @@ -77,7 +75,8 @@ public static Categories Parse(ReadOnlySpan value, bool ignoreCase = false /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out Categories result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -93,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out Categories result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -108,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out Categories re /// public static Categories? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out Categories result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (Categories?)result : null; } /// @@ -125,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out Categories re /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Categories result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -141,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Categ /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out Categories result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -156,21 +158,121 @@ public static bool TryParse(ReadOnlySpan value, out Categories result) /// public static Categories? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out Categories result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (Categories?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out Categories result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (Categories)number; - return true; + switch (value[0]) + { + case 'A': + case 'a': + switch (value) + { + case { } when value.Equals("Automotive", comparisonType): + result = 2; + return true; + case { } when value.Equals("Arts", comparisonType): + result = 3; + return true; + } + break; + case 'B': + case 'b': + switch (value) + { + case { } when value.Equals("BeautyCare", comparisonType): + result = 4; + return true; + } + break; + case 'E': + case 'e': + switch (value) + { + case { } when value.Equals("Electronics", comparisonType): + result = 0; + return true; + } + break; + case 'F': + case 'f': + switch (value) + { + case { } when value.Equals("Food", comparisonType): + result = 1; + return true; + case { } when value.Equals("Fashion", comparisonType): + result = 5; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -192,15 +294,8 @@ public static bool TryParse( StringComparison comparisonType, out Categories result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (Categories)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -219,7 +314,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out Categories result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -234,7 +330,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static Categories? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out Categories result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (Categories?)result : null; } /// @@ -251,7 +347,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static Categories? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out Categories result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (Categories?)result : null; } /// Retrieves an array of the values of the constants in the Categories enumeration. @@ -283,11 +379,5 @@ public static string[] GetNames() "Fashion", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesValidation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesValidation.g.cs index 7ec80c2..e59e4fe 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesValidation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.CategoriesValidation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class CategoriesValidation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursEnumInfo.g.cs index e668e1c..3e71888 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursEnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursEnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class ColoursMetadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 5; /// The string representation of name. @@ -33,7 +34,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 5; /// The UTF-8 representation of name. @@ -45,169 +46,5 @@ public static partial class Utf8Name /// The UTF-8 representation of name. public static ReadOnlySpan Green => new byte[5] { 71, 114, 101, 101, 110 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFlagsFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - if (value == 0) - { - return 1; - } - - int count = 0, foundItemsCount = 0; - if ((value & 4) == 4) - { - value -= 4; - count = checked(count + 5); - foundItemsCount++; - } - if ((value & 2) == 2) - { - value -= 2; - count = checked(count + 4); - foundItemsCount++; - } - if ((value & 1) == 1) - { - value -= 1; - count = checked(count + 3); - foundItemsCount++; - } - - if (value != 0) - { - return null; - } - - const int separatorStringLength = 2; - return checked(count + (separatorStringLength * (foundItemsCount - 1))); - } - - /// - public string? TryGetStringForMember(int value) - { - if (value == 0) - { - return "0"; - } - - Span foundItems = stackalloc int[3]; - int count = 0, foundItemsCount = 0; - if ((value & 4) == 4) - { - value -= 4; - count = checked(count + 5); - foundItems[foundItemsCount++] = 4; - } - if ((value & 2) == 2) - { - value -= 2; - count = checked(count + 4); - foundItems[foundItemsCount++] = 2; - } - if ((value & 1) == 1) - { - value -= 1; - count = checked(count + 3); - foundItems[foundItemsCount++] = 1; - } - - if (value != 0) - { - return null; - } - - if (foundItemsCount == 1) - { - return GetStringForSingleMember(foundItems[0]); - } - - return EnumStringFormatter.WriteMultipleFoundFlagsNames(this, count, foundItemsCount, foundItems); - } - - public string GetStringForSingleMember(int value) - { - return value switch - { - 1 => "Red", - 2 => "Blue", - 4 => "Green", - _ => throw new ArgumentOutOfRangeException() - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'R': - case 'r': - switch (value) - { - case { } when value.Equals("Red", comparisonType): - result = 1; - return true; - } - goto default; - case 'B': - case 'b': - switch (value) - { - case { } when value.Equals("Blue", comparisonType): - result = 2; - return true; - } - goto default; - case 'G': - case 'g': - switch (value) - { - case { } when value.Equals("Green", comparisonType): - result = 4; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursExtensions.g.cs index ab3f87d..165bb86 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursExtensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursExtensions.g.cs @@ -11,21 +11,21 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class ColoursExtensions { - private static readonly ColoursMetadata.StringFormatter s_stringFormatter = ColoursMetadata.StringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this Colours value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return FormatFlagNames((int)value) + ?? ((int)value).ToString(); } /// Determines whether one or more bit fields are set in the current instance. /// An enumeration value. /// if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, . + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasFlagFast(this Colours value, Colours flag) { return (value & flag) == flag; @@ -36,14 +36,143 @@ public static bool HasFlagFast(this Colours value, Colours flag) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this Colours value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return FormatFlagNamesLength((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this Colours value) { - return ColoursValidation.IsDefined(value); + return (int)value switch + { + 1 => true, + 2 => true, + 4 => true, + _ => false + }; + } + + private static int? FormatFlagNamesLength(int value) + { + int? fastResult = GetNameLengthInlined(value); + if (fastResult is not null) + { + return fastResult.Value; + } + + if (value == 0) + { + return 1; + } + + int count = 0, foundItemsCount = 0; + if (true) + { + if ((value & 4) == 4) + { + value -= 4; + count = checked(count + 5); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 2) == 2) + { + value -= 2; + count = checked(count + 4); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 1) == 1) + { + value -= 1; + count = checked(count + 3); + foundItemsCount++; + if (value == 0) goto CountLength; + } + } + + if (value != 0) + { + return null; + } + + CountLength: + const int separatorStringLength = 2; + return checked(count + (separatorStringLength * (foundItemsCount - 1))); + } + + private static readonly string[] s_formatNames = new string[3] { "Green", "Blue", "Red" }; + + private static string? FormatFlagNames(int value) + { + string? result = GetNameInlined(value); + if (result is null) + { + Span foundItems = stackalloc int[3]; + if (TryFindFlagsNames(value, foundItems, out int foundItemsCount, out int resultLength)) + { + result = EnumStringFormatter.WriteMultipleFoundFlagsNames(s_formatNames, foundItems, foundItemsCount, resultLength); + } + } + + return result; + } + + private static bool TryFindFlagsNames(int value, Span foundItems, out int foundItemsCount, out int resultLength) + { + resultLength = 0; + foundItemsCount = 0; + if (true) + { + if ((value & 4) == 4) + { + value -= 4; + resultLength = checked(resultLength + 5); + foundItems[foundItemsCount++] = 0; + if (value == 0) return true; + } + if ((value & 2) == 2) + { + value -= 2; + resultLength = checked(resultLength + 4); + foundItems[foundItemsCount++] = 1; + if (value == 0) return true; + } + if ((value & 1) == 1) + { + value -= 1; + resultLength = checked(resultLength + 3); + foundItems[foundItemsCount++] = 2; + if (value == 0) return true; + } + } + + return value == 0; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + 0 => 1, + 1 => 3, + 2 => 4, + 4 => 5, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + 0 => "0", + 1 => "Red", + 2 => "Blue", + 4 => "Green", + _ => null + }; } #if NET5_0_OR_GREATER diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursFactory.g.cs index 7f86a4b..ba2b44d 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursFactory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursFactory.g.cs @@ -12,11 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class ColoursFactory { - private static readonly ColoursMetadata.StringParser s_stringParser = ColoursMetadata.StringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -28,9 +26,9 @@ public static partial class ColoursFactory /// is empty or does not represent a valid value. public static Colours Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (Colours)result; } /// @@ -43,8 +41,8 @@ public static Colours Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static Colours Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (Colours)result; } /// @@ -59,8 +57,8 @@ public static Colours Parse(ReadOnlySpan value, bool ignoreCase = false) public static Colours? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (Colours)result; } /// @@ -77,7 +75,8 @@ public static Colours Parse(ReadOnlySpan value, bool ignoreCase = false) /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out Colours result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -93,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out Colours result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -108,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out Colours resul /// public static Colours? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out Colours result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (Colours?)result : null; } /// @@ -125,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out Colours resul /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Colours result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -141,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Colou /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out Colours result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -156,21 +158,121 @@ public static bool TryParse(ReadOnlySpan value, out Colours result) /// public static Colours? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out Colours result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (Colours?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool parsed = true; + int localResult = 0; + foreach (var item in new FlagsEnumTokenizer(value)) + { + bool success = TryParseSingleName(item, comparisonType, out int singleValue); + if (!success) + { + parsed = false; + break; + } + + localResult |= singleValue; + } + + if (parsed) + { + result = localResult; + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + result = 0; + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out Colours result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (Colours)number; - return true; + switch (value[0]) + { + case 'B': + case 'b': + switch (value) + { + case { } when value.Equals("Blue", comparisonType): + result = 2; + return true; + } + break; + case 'G': + case 'g': + switch (value) + { + case { } when value.Equals("Green", comparisonType): + result = 4; + return true; + } + break; + case 'R': + case 'r': + switch (value) + { + case { } when value.Equals("Red", comparisonType): + result = 1; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -192,15 +294,8 @@ public static bool TryParse( StringComparison comparisonType, out Colours result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (Colours)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -219,7 +314,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out Colours result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -234,7 +330,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static Colours? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out Colours result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (Colours?)result : null; } /// @@ -251,7 +347,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static Colours? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out Colours result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (Colours?)result : null; } /// Retrieves an array of the values of the constants in the Colours enumeration. @@ -277,11 +373,5 @@ public static string[] GetNames() "Green", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursValidation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursValidation.g.cs index 95eaa95..564d796 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursValidation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ColoursValidation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class ColoursValidation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeEnumInfo.g.cs deleted file mode 100644 index 3679925..0000000 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeEnumInfo.g.cs +++ /dev/null @@ -1,126 +0,0 @@ -// -#nullable enable - -using System; -using System.Runtime.CompilerServices; -using Raiqub.Generators.EnumUtilities.Formatters; -using Raiqub.Generators.EnumUtilities.Parsers; - -#pragma warning disable CS1591 // publicly visible type or member must be documented - -namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models -{ - [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] - internal static partial class ErrorCodeMetadata - { - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(ushort value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(ushort value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(ushort value) - { - return value switch - { - 0 => 4, - 1 => 7, - 100 => 14, - 200 => 14, - _ => null - }; - } - - /// - public string? TryGetStringForMember(ushort value) - { - return value switch - { - 0 => "None", - 1 => "Unknown", - 100 => "ConnectionLost", - 200 => "OutlierReading", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ushort BitwiseOr(ushort value1, ushort value2) => unchecked((ushort)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out ushort result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out ushort result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'N': - case 'n': - switch (value) - { - case { } when value.Equals("None", comparisonType): - result = 0; - return true; - } - goto default; - case 'U': - case 'u': - switch (value) - { - case { } when value.Equals("Unknown", comparisonType): - result = 1; - return true; - } - goto default; - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("ConnectionLost", comparisonType): - result = 100; - return true; - } - goto default; - case 'O': - case 'o': - switch (value) - { - case { } when value.Equals("OutlierReading", comparisonType): - result = 200; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } - } -} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeExtensions.g.cs new file mode 100644 index 0000000..1686696 --- /dev/null +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeExtensions.g.cs @@ -0,0 +1,53 @@ +// +#nullable enable + +using System; +using System.Runtime.CompilerServices; +using Raiqub.Generators.EnumUtilities.Formatters; + +#pragma warning disable CS1591 // publicly visible type or member must be documented + +namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] + internal static partial class ErrorCodeExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? ToJsonString(this ErrorCode value) + { + return GetJsonStringInlined((ushort)value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? GetJsonStringLength(this ErrorCode value) + { + return GetJsonStringLengthInlined((ushort)value); + } + + private static int? GetJsonStringLengthInlined(ushort value) + { + return value switch + { + 0 => 3, + 1 => 3, + 100 => 3, + 200 => 3, + _ => null + }; + } + + private static string? GetJsonStringInlined(ushort value) + { + return value switch + { + 0 => "NON", + 1 => "UNK", + 100 => "CNX", + 200 => "OUT", + _ => null + }; + } + } +} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeFactory.g.cs new file mode 100644 index 0000000..7df173d --- /dev/null +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeFactory.g.cs @@ -0,0 +1,244 @@ +// +#nullable enable + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Runtime.CompilerServices; +using Raiqub.Generators.EnumUtilities.Parsers; + +#pragma warning disable CS1591 // publicly visible type or member must be documented + +namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] + internal static partial class ErrorCodeFactory + { + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value. Note that this value need not be a member of the ErrorCode enumeration. + /// is . + /// is empty or does not represent a valid value. + public static ErrorCode ParseJsonString(string value, bool ignoreCase = false) + { + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (ErrorCode)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value. Note that this value need not be a member of the ErrorCode enumeration. + /// is empty or does not represent a valid value. + public static ErrorCode ParseJsonString(ReadOnlySpan value, bool ignoreCase = false) + { + TryParseJsonString(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (ErrorCode)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value or null. Note that this value need not be a member of the ErrorCode enumeration. + /// is empty or does not represent a valid value. + [return: NotNullIfNotNull("value")] + public static ErrorCode? ParseJsonStringOrNull(string? value, bool ignoreCase = false) + { + if (value is null) return null; + TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (ErrorCode)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// When this method returns, result contains an object of type ErrorCode whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of ErrorCode. Note that this value need not be a member of the ErrorCode enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString([NotNullWhen(true)] string? value, bool ignoreCase, out ErrorCode result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// + /// When this method returns, result contains an object of type ErrorCode whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of ErrorCode. Note that this value need not be a member of the ErrorCode enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString([NotNullWhen(true)] string? value, out ErrorCode result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// Contains an object of type ErrorCode whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains a null value. + /// + public static ErrorCode? TryParseJsonString(string? value, bool ignoreCase = false) + { + return TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (ErrorCode?)result : null; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// When this method returns, result contains an object of type ErrorCode whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of ErrorCode. Note that this value need not be a member of the ErrorCode enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString(ReadOnlySpan value, bool ignoreCase, out ErrorCode result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// + /// When this method returns, result contains an object of type ErrorCode whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of ErrorCode. Note that this value need not be a member of the ErrorCode enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString(ReadOnlySpan value, out ErrorCode result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// Contains an object of type ErrorCode whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains a null value. + /// + public static ErrorCode? TryParseJsonString(ReadOnlySpan value, bool ignoreCase = false) + { + return TryParseJsonString(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (ErrorCode?)result : null; + } + + private static bool TryParseJsonString(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out ushort result) + { + if (!value.IsEmpty) + { + return TryParseNonNumericJsonString(value, comparisonType, throwOnFailure, out result); + } + + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericJsonString(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out ushort result) + { + bool success = TryParseSingleJsonString(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; + } + + private static bool TryParseSingleJsonString(ReadOnlySpan value, StringComparison comparisonType, out ushort result) + { + if (value.IsEmpty) + { + result = 0; + return false; + } + + switch (value[0]) + { + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("CNX", comparisonType): + result = 100; + return true; + } + break; + case 'N': + case 'n': + switch (value) + { + case { } when value.Equals("NON", comparisonType): + result = 0; + return true; + } + break; + case 'O': + case 'o': + switch (value) + { + case { } when value.Equals("OUT", comparisonType): + result = 200; + return true; + } + break; + case 'U': + case 'u': + switch (value) + { + case { } when value.Equals("UNK", comparisonType): + result = 1; + return true; + } + break; + } + + result = 0; + return false; + } + } +} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeJsonConverter.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeJsonConverter.g.cs index dbb3656..6d1ec57 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeJsonConverter.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.ErrorCodeJsonConverter.g.cs @@ -2,6 +2,7 @@ #nullable enable using System; +using System.Buffers; using System.Text.Json; using System.Text.Json.Serialization; using Raiqub.Generators.EnumUtilities.Formatters; @@ -12,104 +13,78 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal sealed class ErrorCodeJsonConverter : JsonConverter { - private const int MaxBytesLength = 3; - private const int MaxCharsLength = 3; - - private static readonly ErrorCodeMetadata.StringFormatter s_stringFormatter = ErrorCodeMetadata.StringFormatter.Instance; - private static readonly ErrorCodeMetadata.StringParser s_stringParser = ErrorCodeMetadata.StringParser.Instance; + private const int MaxCharStack = 256; public override ErrorCode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) - return (ErrorCode)ReadFromString(ref reader); + return ReadFromString(ref reader); return (ErrorCode)0; } - #if NET7_0_OR_GREATER - public override void Write(Utf8JsonWriter writer, ErrorCode value, JsonSerializerOptions options) { - switch ((ushort)value) + string? jsonString = value.ToJsonString(); + if (jsonString is not null) + { + writer.WriteStringValue(jsonString); + } + else { - case 0: - writer.WriteStringValue("NON"u8); - break; - case 1: - writer.WriteStringValue("UNK"u8); - break; - case 100: - writer.WriteStringValue("CNX"u8); - break; - case 200: - writer.WriteStringValue("OUT"u8); - break; - default: - string strValue = EnumStringFormatter.GetString((ushort)value, s_stringFormatter); - writer.WriteStringValue(strValue); - break; + jsonString = ((ErrorCode)0).ToJsonString(); + if (jsonString is not null) + writer.WriteStringValue(jsonString); + else + throw new JsonException(); } } - private ushort ReadFromString(ref Utf8JsonReader reader) + #if NET7_0_OR_GREATER + + private ErrorCode ReadFromString(ref Utf8JsonReader reader) { int length = reader.HasValueSequence ? checked((int)reader.ValueSequence.Length) : reader.ValueSpan.Length; - if (length > MaxBytesLength) - return (ushort)0; - Span name = stackalloc char[MaxBytesLength]; - int charsWritten = reader.CopyString(name); - name = name.Slice(0, charsWritten); - - return name switch + char[]? rented = null; + Span name = length <= MaxCharStack ? stackalloc char[MaxCharStack] : (rented = ArrayPool.Shared.Rent(length)); + try { - "NON" => (ushort)0, - "UNK" => (ushort)1, - "CNX" => (ushort)100, - "OUT" => (ushort)200, - _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out ushort result) ? result : (ushort)0 - }; - } + int charsWritten = reader.CopyString(name); + name = name.Slice(0, charsWritten); - #else + bool isParsed = ErrorCodeFactory.TryParseJsonString(name, ignoreCase: false, out ErrorCode result); + if (!isParsed) + { + return (ErrorCode)0; + } - public override void Write(Utf8JsonWriter writer, ErrorCode value, JsonSerializerOptions options) - { - switch ((ushort)value) + return result; + } + finally { - case 0: - writer.WriteStringValue("NON"); - break; - case 1: - writer.WriteStringValue("UNK"); - break; - case 100: - writer.WriteStringValue("CNX"); - break; - case 200: - writer.WriteStringValue("OUT"); - break; - default: - string strValue = EnumStringFormatter.GetString((ushort)value, s_stringFormatter); - writer.WriteStringValue(strValue); - break; + if (rented != null) + { + ArrayPool.Shared.Return(rented); + } } } - private ushort ReadFromString(ref Utf8JsonReader reader) + #else + + private ErrorCode ReadFromString(ref Utf8JsonReader reader) { var name = reader.GetString(); - return name switch + bool isParsed = ErrorCodeFactory.TryParseJsonString(name, ignoreCase: false, out ErrorCode result); + if (!isParsed) { - "NON" => (ushort)0, - "UNK" => (ushort)1, - "CNX" => (ushort)100, - "OUT" => (ushort)200, - _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out ushort result) ? result : (ushort)0 - }; + return (ErrorCode)0; + } + + return result; } #endif diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesEnumInfo.g.cs index 0892590..59d9e7d 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesEnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesEnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class HumanStatesMetadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 8; /// The string representation of name. @@ -42,7 +43,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 8; /// The UTF-8 representation of name. @@ -63,134 +64,5 @@ public static partial class Utf8Name /// The UTF-8 representation of name. public static ReadOnlySpan Relaxing => new byte[8] { 82, 101, 108, 97, 120, 105, 110, 103 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 1 => 4, - 2 => 7, - 3 => 8, - 4 => 6, - 5 => 4, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 1 => "Idle", - 2 => "Working", - 3 => "Sleeping", - 4 => "Eating", - 5 => "Dead", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'I': - case 'i': - switch (value) - { - case { } when value.Equals("Idle", comparisonType): - result = 1; - return true; - } - goto default; - case 'W': - case 'w': - switch (value) - { - case { } when value.Equals("Working", comparisonType): - result = 2; - return true; - } - goto default; - case 'S': - case 's': - switch (value) - { - case { } when value.Equals("Sleeping", comparisonType): - result = 3; - return true; - } - goto default; - case 'E': - case 'e': - switch (value) - { - case { } when value.Equals("Eating", comparisonType): - result = 4; - return true; - } - goto default; - case 'D': - case 'd': - switch (value) - { - case { } when value.Equals("Dead", comparisonType): - result = 5; - return true; - } - goto default; - case 'R': - case 'r': - switch (value) - { - case { } when value.Equals("Relaxing", comparisonType): - result = 1; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesExtensions.g.cs index 79d35e6..82a21ca 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesExtensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesExtensions.g.cs @@ -11,16 +11,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class HumanStatesExtensions { - private static readonly HumanStatesMetadata.StringFormatter s_stringFormatter = HumanStatesMetadata.StringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this HumanStates value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return GetNameInlined((int)value) + ?? ((int)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -28,14 +27,51 @@ public static string ToStringFast(this HumanStates value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this HumanStates value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return GetNameLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this HumanStates value) { - return HumanStatesValidation.IsDefined(value); + return (int)value switch + { + 1 => true, + 2 => true, + 3 => true, + 4 => true, + 5 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + 0 => 1, + 1 => 4, + 2 => 7, + 3 => 8, + 4 => 6, + 5 => 4, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + 0 => "0", + 1 => "Idle", + 2 => "Working", + 3 => "Sleeping", + 4 => "Eating", + 5 => "Dead", + _ => null + }; } /// Adds two enumerations and replaces the first integer with the sum, as an atomic operation. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesFactory.g.cs index b93b41f..63b9213 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesFactory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesFactory.g.cs @@ -12,11 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class HumanStatesFactory { - private static readonly HumanStatesMetadata.StringParser s_stringParser = HumanStatesMetadata.StringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -28,9 +26,9 @@ public static partial class HumanStatesFactory /// is empty or does not represent a valid value. public static HumanStates Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (HumanStates)result; } /// @@ -43,8 +41,8 @@ public static HumanStates Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static HumanStates Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (HumanStates)result; } /// @@ -59,8 +57,8 @@ public static HumanStates Parse(ReadOnlySpan value, bool ignoreCase = fals public static HumanStates? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (HumanStates)result; } /// @@ -77,7 +75,8 @@ public static HumanStates Parse(ReadOnlySpan value, bool ignoreCase = fals /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out HumanStates result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -93,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out HumanStates result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -108,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out HumanStates r /// public static HumanStates? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out HumanStates result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (HumanStates?)result : null; } /// @@ -125,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out HumanStates r /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out HumanStates result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -141,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Human /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out HumanStates result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -156,21 +158,133 @@ public static bool TryParse(ReadOnlySpan value, out HumanStates result) /// public static HumanStates? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out HumanStates result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (HumanStates?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out HumanStates result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (HumanStates)number; - return true; + switch (value[0]) + { + case 'D': + case 'd': + switch (value) + { + case { } when value.Equals("Dead", comparisonType): + result = 5; + return true; + } + break; + case 'E': + case 'e': + switch (value) + { + case { } when value.Equals("Eating", comparisonType): + result = 4; + return true; + } + break; + case 'I': + case 'i': + switch (value) + { + case { } when value.Equals("Idle", comparisonType): + result = 1; + return true; + } + break; + case 'R': + case 'r': + switch (value) + { + case { } when value.Equals("Relaxing", comparisonType): + result = 1; + return true; + } + break; + case 'S': + case 's': + switch (value) + { + case { } when value.Equals("Sleeping", comparisonType): + result = 3; + return true; + } + break; + case 'W': + case 'w': + switch (value) + { + case { } when value.Equals("Working", comparisonType): + result = 2; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -192,15 +306,8 @@ public static bool TryParse( StringComparison comparisonType, out HumanStates result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (HumanStates)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -219,7 +326,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out HumanStates result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -234,7 +342,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static HumanStates? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out HumanStates result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (HumanStates?)result : null; } /// @@ -251,7 +359,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static HumanStates? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out HumanStates result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (HumanStates?)result : null; } /// Retrieves an array of the values of the constants in the HumanStates enumeration. @@ -282,11 +390,5 @@ public static string[] GetNames() "Relaxing", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesValidation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesValidation.g.cs index 62acfd4..b7329c1 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesValidation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.HumanStatesValidation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class HumanStatesValidation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1EnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1EnumInfo.g.cs index bb4b8a9..ee496ff 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1EnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1EnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal static partial class MyEnum1Metadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 4; /// The string representation of name. @@ -33,7 +34,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 4; /// The UTF-8 representation of name. @@ -45,103 +46,5 @@ public static partial class Utf8Name /// The UTF-8 representation of name. public static ReadOnlySpan Two => new byte[3] { 84, 119, 111 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 0 => 4, - 1 => 3, - 2 => 3, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 0 => "Zero", - 1 => "One", - 2 => "Two", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'Z': - case 'z': - switch (value) - { - case { } when value.Equals("Zero", comparisonType): - result = 0; - return true; - } - goto default; - case 'O': - case 'o': - switch (value) - { - case { } when value.Equals("One", comparisonType): - result = 1; - return true; - } - goto default; - case 'T': - case 't': - switch (value) - { - case { } when value.Equals("Two", comparisonType): - result = 2; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Extensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Extensions.g.cs index 5cb88a6..5393104 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Extensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Extensions.g.cs @@ -11,16 +11,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal static partial class MyEnum1Extensions { - private static readonly MyEnum1Metadata.StringFormatter s_stringFormatter = MyEnum1Metadata.StringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this NestedInClass.MyEnum1 value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return GetNameInlined((int)value) + ?? ((int)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -28,14 +27,43 @@ public static string ToStringFast(this NestedInClass.MyEnum1 value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this NestedInClass.MyEnum1 value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return GetNameLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this NestedInClass.MyEnum1 value) { - return MyEnum1Validation.IsDefined(value); + return (int)value switch + { + 0 => true, + 1 => true, + 2 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + 0 => 4, + 1 => 3, + 2 => 3, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + 0 => "Zero", + 1 => "One", + 2 => "Two", + _ => null + }; } /// Adds two enumerations and replaces the first integer with the sum, as an atomic operation. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Factory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Factory.g.cs index a5363c3..16345e3 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Factory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Factory.g.cs @@ -12,11 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal static partial class MyEnum1Factory { - private static readonly MyEnum1Metadata.StringParser s_stringParser = MyEnum1Metadata.StringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -28,9 +26,9 @@ internal static partial class MyEnum1Factory /// is empty or does not represent a valid value. public static NestedInClass.MyEnum1 Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum1)result; } /// @@ -43,8 +41,8 @@ public static NestedInClass.MyEnum1 Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static NestedInClass.MyEnum1 Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum1)result; } /// @@ -59,8 +57,8 @@ public static NestedInClass.MyEnum1 Parse(ReadOnlySpan value, bool ignoreC public static NestedInClass.MyEnum1? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum1)result; } /// @@ -77,7 +75,8 @@ public static NestedInClass.MyEnum1 Parse(ReadOnlySpan value, bool ignoreC /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out NestedInClass.MyEnum1 result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -93,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out NestedInClass.MyEnum1 result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -108,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out NestedInClass /// public static NestedInClass.MyEnum1? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out NestedInClass.MyEnum1 result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum1?)result : null; } /// @@ -125,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out NestedInClass /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out NestedInClass.MyEnum1 result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -141,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Neste /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out NestedInClass.MyEnum1 result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -156,21 +158,106 @@ public static bool TryParse(ReadOnlySpan value, out NestedInClass.MyEnum1 /// public static NestedInClass.MyEnum1? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out NestedInClass.MyEnum1 result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum1?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out NestedInClass.MyEnum1 result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (NestedInClass.MyEnum1)number; - return true; + switch (value[0]) + { + case 'O': + case 'o': + switch (value) + { + case { } when value.Equals("One", comparisonType): + result = 1; + return true; + } + break; + case 'T': + case 't': + switch (value) + { + case { } when value.Equals("Two", comparisonType): + result = 2; + return true; + } + break; + case 'Z': + case 'z': + switch (value) + { + case { } when value.Equals("Zero", comparisonType): + result = 0; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -192,15 +279,8 @@ public static bool TryParse( StringComparison comparisonType, out NestedInClass.MyEnum1 result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (NestedInClass.MyEnum1)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -219,7 +299,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out NestedInClass.MyEnum1 result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -234,7 +315,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static NestedInClass.MyEnum1? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out NestedInClass.MyEnum1 result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum1?)result : null; } /// @@ -251,7 +332,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static NestedInClass.MyEnum1? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out NestedInClass.MyEnum1 result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum1?)result : null; } /// Retrieves an array of the values of the constants in the MyEnum1 enumeration. @@ -277,11 +358,5 @@ public static string[] GetNames() "Two", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Validation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Validation.g.cs index 1f1a10f..bae9527 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Validation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum1Validation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal static partial class MyEnum1Validation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2EnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2EnumInfo.g.cs index f8506e5..fd35c36 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2EnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2EnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal static partial class MyEnum2Metadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 6; /// The string representation of name. @@ -36,7 +37,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 6; /// The UTF-8 representation of name. @@ -55,246 +56,39 @@ public static partial class Utf8Name /// Provides constant values for serialized members values. public static partial class SerializedValue { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by serializing a value to string, based on defined members. public const int MaxCharsLength = 11; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Credit = "Credit card"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Debit = "Debit card"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Cash = "Cash"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Cheque = "Cheque"; } - /// Provides static values for UTF-8 encoded members serialized values. + /// Provides static values for UTF-8 encoded serialized members values. public static partial class Utf8SerializedValue { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by serializing a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 11; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Credit => new byte[11] { 67, 114, 101, 100, 105, 116, 32, 99, 97, 114, 100 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Debit => new byte[10] { 68, 101, 98, 105, 116, 32, 99, 97, 114, 100 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Cash => new byte[4] { 67, 97, 115, 104 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Cheque => new byte[6] { 67, 104, 101, 113, 117, 101 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 0 => 6, - 1 => 5, - 2 => 4, - 3 => 6, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 0 => "Credit", - 1 => "Debit", - 2 => "Cash", - 3 => "Cheque", - _ => null - }; - } - } - - /// Provides support for formatting serialized values. - internal sealed partial class SerializationStringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static SerializationStringFormatter Instance = new SerializationStringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 0 => 11, - 1 => 10, - 2 => 4, - 3 => 6, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 0 => "Credit card", - 1 => "Debit card", - 2 => "Cash", - 3 => "Cheque", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser, IEnumDescriptionParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("Credit", comparisonType): - result = 0; - return true; - case { } when value.Equals("Cash", comparisonType): - result = 2; - return true; - case { } when value.Equals("Cheque", comparisonType): - result = 3; - return true; - } - goto default; - case 'D': - case 'd': - switch (value) - { - case { } when value.Equals("Debit", comparisonType): - result = 1; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - - /// - public bool TryParseDescription(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - switch (value) - { - case { } s when s.Equals("The payment by using physical cash", comparisonType): - result = 2; - return true; - default: - result = default; - return false; - } - } - } - - /// Provides support for parsing serialized values. - internal sealed partial class SerializationStringParser : IEnumParser - { - /// Gets the singleton instance of the class. - public static SerializationStringParser Instance = new SerializationStringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("Credit card", comparisonType): - result = 0; - return true; - case { } when value.Equals("Cash", comparisonType): - result = 2; - return true; - case { } when value.Equals("Cheque", comparisonType): - result = 3; - return true; - } - goto default; - case 'D': - case 'd': - switch (value) - { - case { } when value.Equals("Debit card", comparisonType): - result = 1; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Extensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Extensions.g.cs index 90ae8af..3284ffd 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Extensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Extensions.g.cs @@ -11,17 +11,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal static partial class MyEnum2Extensions { - private static readonly MyEnum2Metadata.StringFormatter s_stringFormatter = MyEnum2Metadata.StringFormatter.Instance; - private static readonly MyEnum2Metadata.SerializationStringFormatter s_serializationStringFormatter = MyEnum2Metadata.SerializationStringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this NestedInClass.MyEnum2 value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return GetNameInlined((int)value) + ?? ((int)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -29,14 +27,46 @@ public static string ToStringFast(this NestedInClass.MyEnum2 value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this NestedInClass.MyEnum2 value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return GetNameLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this NestedInClass.MyEnum2 value) { - return MyEnum2Validation.IsDefined(value); + return (int)value switch + { + 0 => true, + 1 => true, + 2 => true, + 3 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + 0 => 6, + 1 => 5, + 2 => 4, + 3 => 6, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + 0 => "Credit", + 1 => "Debit", + 2 => "Cash", + 3 => "Cheque", + _ => null + }; } /// Adds two enumerations and replaces the first integer with the sum, as an atomic operation. @@ -95,12 +125,38 @@ public static NestedInClass.MyEnum2 InterlockedExchange(this ref NestedInClass.M public static string ToEnumMemberValue(this NestedInClass.MyEnum2 value) { - return EnumStringFormatter.GetString((int)value, s_serializationStringFormatter); + return GetEnumMemberValueInlined((int)value) + ?? ((int)value).ToString(); } public static int GetEnumMemberValueStringLength(this NestedInClass.MyEnum2 value) { - return EnumStringFormatter.GetStringLength((int)value, s_serializationStringFormatter); + return GetEnumMemberValueLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); + } + + private static int? GetEnumMemberValueLengthInlined(int value) + { + return value switch + { + 0 => 11, + 1 => 10, + 2 => 4, + 3 => 6, + _ => null + }; + } + + private static string? GetEnumMemberValueInlined(int value) + { + return value switch + { + 0 => "Credit card", + 1 => "Debit card", + 2 => "Cash", + 3 => "Cheque", + _ => null + }; } public static string? GetDescription(this NestedInClass.MyEnum2 value) diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Factory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Factory.g.cs index 1b337f4..c756d7e 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Factory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Factory.g.cs @@ -12,12 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal static partial class MyEnum2Factory { - private static readonly MyEnum2Metadata.StringParser s_stringParser = MyEnum2Metadata.StringParser.Instance; - private static readonly MyEnum2Metadata.SerializationStringParser s_serializationStringParser = MyEnum2Metadata.SerializationStringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -29,9 +26,9 @@ internal static partial class MyEnum2Factory /// is empty or does not represent a valid value. public static NestedInClass.MyEnum2 Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum2)result; } /// @@ -44,8 +41,8 @@ public static NestedInClass.MyEnum2 Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static NestedInClass.MyEnum2 Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum2)result; } /// @@ -60,8 +57,8 @@ public static NestedInClass.MyEnum2 Parse(ReadOnlySpan value, bool ignoreC public static NestedInClass.MyEnum2? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum2)result; } /// @@ -78,7 +75,8 @@ public static NestedInClass.MyEnum2 Parse(ReadOnlySpan value, bool ignoreC /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out NestedInClass.MyEnum2 result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -94,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out NestedInClass.MyEnum2 result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -109,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out NestedInClass /// public static NestedInClass.MyEnum2? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out NestedInClass.MyEnum2 result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum2?)result : null; } /// @@ -126,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out NestedInClass /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out NestedInClass.MyEnum2 result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -142,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Neste /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out NestedInClass.MyEnum2 result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -157,21 +158,103 @@ public static bool TryParse(ReadOnlySpan value, out NestedInClass.MyEnum2 /// public static NestedInClass.MyEnum2? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out NestedInClass.MyEnum2 result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum2?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out NestedInClass.MyEnum2 result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (NestedInClass.MyEnum2)number; - return true; + switch (value[0]) + { + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("Credit", comparisonType): + result = 0; + return true; + case { } when value.Equals("Cash", comparisonType): + result = 2; + return true; + case { } when value.Equals("Cheque", comparisonType): + result = 3; + return true; + } + break; + case 'D': + case 'd': + switch (value) + { + case { } when value.Equals("Debit", comparisonType): + result = 1; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -193,15 +276,8 @@ public static bool TryParse( StringComparison comparisonType, out NestedInClass.MyEnum2 result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (NestedInClass.MyEnum2)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -220,7 +296,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out NestedInClass.MyEnum2 result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -235,7 +312,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static NestedInClass.MyEnum2? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out NestedInClass.MyEnum2 result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum2?)result : null; } /// @@ -252,7 +329,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static NestedInClass.MyEnum2? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out NestedInClass.MyEnum2 result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum2?)result : null; } /// @@ -265,9 +342,9 @@ public static bool TryParseIgnoreCase( /// is empty or does not represent a valid value. public static NestedInClass.MyEnum2 ParseFromEnumMemberValue(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum2)result; } /// @@ -279,8 +356,8 @@ public static NestedInClass.MyEnum2 ParseFromEnumMemberValue(string value, bool /// is empty or does not represent a valid value. public static NestedInClass.MyEnum2 ParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum2)result; } /// @@ -294,8 +371,8 @@ public static NestedInClass.MyEnum2 ParseFromEnumMemberValue(ReadOnlySpan public static NestedInClass.MyEnum2? ParseFromEnumMemberValueOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum2)result; } /// @@ -312,7 +389,8 @@ public static NestedInClass.MyEnum2 ParseFromEnumMemberValue(ReadOnlySpan /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, bool ignoreCase, out NestedInClass.MyEnum2 result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -328,7 +406,8 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, out NestedInClass.MyEnum2 result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -342,7 +421,7 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// public static NestedInClass.MyEnum2? TryParseFromEnumMemberValue(string? value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out NestedInClass.MyEnum2 result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum2?)result : null; } /// @@ -359,7 +438,8 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, out NestedInClass.MyEnum2 result) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -375,7 +455,8 @@ public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ig /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out NestedInClass.MyEnum2 result) { - return TryParseFromEnumMemberValue(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -389,25 +470,103 @@ public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out Nes /// public static NestedInClass.MyEnum2? TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out NestedInClass.MyEnum2 result) ? result : null; + return TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum2?)result : null; + } + + private static bool TryParseEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericEnumMemberValue(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericEnumMemberValue(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; } - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out NestedInClass.MyEnum2 result) + private static bool TryParseNonNumericEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) { - return TryParseFromEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure, out result); + bool success = TryParseSingleEnumMemberValue(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out NestedInClass.MyEnum2 result) + private static bool TryParseSingleEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, out int result) { - bool success = EnumStringParser.TryParse(value, s_serializationStringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (NestedInClass.MyEnum2)number; - return true; + switch (value[0]) + { + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("Credit card", comparisonType): + result = 0; + return true; + case { } when value.Equals("Cash", comparisonType): + result = 2; + return true; + case { } when value.Equals("Cheque", comparisonType): + result = 3; + return true; + } + break; + case 'D': + case 'd': + switch (value) + { + case { } when value.Equals("Debit card", comparisonType): + result = 1; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -429,7 +588,8 @@ public static bool TryParseFromEnumMemberValue( StringComparison comparisonType, out NestedInClass.MyEnum2 result) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -446,71 +606,119 @@ public static bool TryParseFromEnumMemberValue( [Obsolete("Use TryParseFromEnumMemberValue overload with 'ignoreCase' parameter")] public static NestedInClass.MyEnum2? TryParseFromEnumMemberValue(string? value, StringComparison comparisonType) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out NestedInClass.MyEnum2 result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum2?)result : null; } public static NestedInClass.MyEnum2 CreateFromDescription(string description, StringComparison comparisonType = StringComparison.Ordinal) { - if (description is null) ThrowArgumentNullException(nameof(description)); - TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); - return result; + if (description is null) ThrowHelper.ThrowArgumentNullException(nameof(description)); + TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum2)result; } public static NestedInClass.MyEnum2 CreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal) { - TryCreateFromDescription(description, comparisonType, throwOnFailure: true, out var result); - return result; + TryParseDescription(description, comparisonType, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum2)result; } [return: NotNullIfNotNull("description")] public static NestedInClass.MyEnum2? CreateFromDescriptionOrNull(string? description, StringComparison comparisonType = StringComparison.Ordinal) { if (description is null) return null; - TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); - return result; + TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum2)result; } public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, StringComparison comparisonType, out NestedInClass.MyEnum2 result) { - return TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, out NestedInClass.MyEnum2 result) { - return TryCreateFromDescription(description.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } public static NestedInClass.MyEnum2? TryCreateFromDescription(string? description, StringComparison comparisonType = StringComparison.Ordinal) { - return TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out NestedInClass.MyEnum2 result) ? result : null; + return TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum2?)result : null; } public static bool TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType, out NestedInClass.MyEnum2 result) { - return TryCreateFromDescription(description, comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description, comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } public static bool TryCreateFromDescription(ReadOnlySpan description, out NestedInClass.MyEnum2 result) { - return TryCreateFromDescription(description, StringComparison.Ordinal, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } public static NestedInClass.MyEnum2? TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal) { - return TryCreateFromDescription(description, comparisonType, throwOnFailure: false, out NestedInClass.MyEnum2 result) ? result : null; + return TryParseDescription(description, comparisonType, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum2?)result : null; } - private static bool TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType, bool throwOnFailure, out NestedInClass.MyEnum2 result) + private static bool TryParseDescription(ReadOnlySpan description, StringComparison comparisonType, bool throwOnFailure, out int result) { - bool success = EnumStringParser.TryParseDescription(description, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (!description.IsEmpty) + { + return TryParseNonNumericDescription(description, comparisonType, throwOnFailure, out result); + } + + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(description)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericDescription(ReadOnlySpan description, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleDescription(description, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(description, nameof(description)); + } + + return false; + } + + private static bool TryParseSingleDescription(ReadOnlySpan value, StringComparison comparisonType, out int result) + { + if (value.IsEmpty) { result = 0; return false; } - result = (NestedInClass.MyEnum2)number; - return true; + switch (value[0]) + { + case 'T': + case 't': + switch (value) + { + case { } when value.Equals("The payment by using physical cash", comparisonType): + result = 2; + return true; + } + break; + } + + result = 0; + return false; } public static bool TryCreateFromDisplayShortName( @@ -605,11 +813,5 @@ public static string[] GetNames() "Cheque", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Validation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Validation.g.cs index 4f42f6f..590d0e6 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Validation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum2Validation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] internal static partial class MyEnum2Validation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3EnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3EnumInfo.g.cs index d4efe29..2c2b0c3 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3EnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3EnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class MyEnum3Metadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 9; /// The string representation of name. @@ -45,7 +46,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 9; /// The UTF-8 representation of name. @@ -69,135 +70,5 @@ public static partial class Utf8Name /// The UTF-8 representation of name. public static ReadOnlySpan Sunday => new byte[6] { 83, 117, 110, 100, 97, 121 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 0 => 6, - 1 => 7, - 2 => 9, - 3 => 8, - 4 => 6, - 5 => 8, - 6 => 6, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 0 => "Monday", - 1 => "Tuesday", - 2 => "Wednesday", - 3 => "Thursday", - 4 => "Friday", - 5 => "Saturday", - 6 => "Sunday", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'M': - case 'm': - switch (value) - { - case { } when value.Equals("Monday", comparisonType): - result = 0; - return true; - } - goto default; - case 'T': - case 't': - switch (value) - { - case { } when value.Equals("Tuesday", comparisonType): - result = 1; - return true; - case { } when value.Equals("Thursday", comparisonType): - result = 3; - return true; - } - goto default; - case 'W': - case 'w': - switch (value) - { - case { } when value.Equals("Wednesday", comparisonType): - result = 2; - return true; - } - goto default; - case 'F': - case 'f': - switch (value) - { - case { } when value.Equals("Friday", comparisonType): - result = 4; - return true; - } - goto default; - case 'S': - case 's': - switch (value) - { - case { } when value.Equals("Saturday", comparisonType): - result = 5; - return true; - case { } when value.Equals("Sunday", comparisonType): - result = 6; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Extensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Extensions.g.cs index 0135178..554c9ba 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Extensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Extensions.g.cs @@ -11,16 +11,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class MyEnum3Extensions { - private static readonly MyEnum3Metadata.StringFormatter s_stringFormatter = MyEnum3Metadata.StringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this NestedInClass.MyEnum3 value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return GetNameInlined((int)value) + ?? ((int)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -28,14 +27,55 @@ public static string ToStringFast(this NestedInClass.MyEnum3 value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this NestedInClass.MyEnum3 value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return GetNameLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this NestedInClass.MyEnum3 value) { - return MyEnum3Validation.IsDefined(value); + return (int)value switch + { + 0 => true, + 1 => true, + 2 => true, + 3 => true, + 4 => true, + 5 => true, + 6 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + 0 => 6, + 1 => 7, + 2 => 9, + 3 => 8, + 4 => 6, + 5 => 8, + 6 => 6, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + 0 => "Monday", + 1 => "Tuesday", + 2 => "Wednesday", + 3 => "Thursday", + 4 => "Friday", + 5 => "Saturday", + 6 => "Sunday", + _ => null + }; } /// Adds two enumerations and replaces the first integer with the sum, as an atomic operation. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Factory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Factory.g.cs index 630747b..017370b 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Factory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Factory.g.cs @@ -12,11 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class MyEnum3Factory { - private static readonly MyEnum3Metadata.StringParser s_stringParser = MyEnum3Metadata.StringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -28,9 +26,9 @@ public static partial class MyEnum3Factory /// is empty or does not represent a valid value. public static NestedInClass.MyEnum3 Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum3)result; } /// @@ -43,8 +41,8 @@ public static NestedInClass.MyEnum3 Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static NestedInClass.MyEnum3 Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum3)result; } /// @@ -59,8 +57,8 @@ public static NestedInClass.MyEnum3 Parse(ReadOnlySpan value, bool ignoreC public static NestedInClass.MyEnum3? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NestedInClass.MyEnum3)result; } /// @@ -77,7 +75,8 @@ public static NestedInClass.MyEnum3 Parse(ReadOnlySpan value, bool ignoreC /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out NestedInClass.MyEnum3 result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -93,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out NestedInClass.MyEnum3 result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -108,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out NestedInClass /// public static NestedInClass.MyEnum3? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out NestedInClass.MyEnum3 result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum3?)result : null; } /// @@ -125,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out NestedInClass /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out NestedInClass.MyEnum3 result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -141,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Neste /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out NestedInClass.MyEnum3 result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -156,21 +158,130 @@ public static bool TryParse(ReadOnlySpan value, out NestedInClass.MyEnum3 /// public static NestedInClass.MyEnum3? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out NestedInClass.MyEnum3 result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum3?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out NestedInClass.MyEnum3 result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (NestedInClass.MyEnum3)number; - return true; + switch (value[0]) + { + case 'F': + case 'f': + switch (value) + { + case { } when value.Equals("Friday", comparisonType): + result = 4; + return true; + } + break; + case 'M': + case 'm': + switch (value) + { + case { } when value.Equals("Monday", comparisonType): + result = 0; + return true; + } + break; + case 'S': + case 's': + switch (value) + { + case { } when value.Equals("Saturday", comparisonType): + result = 5; + return true; + case { } when value.Equals("Sunday", comparisonType): + result = 6; + return true; + } + break; + case 'T': + case 't': + switch (value) + { + case { } when value.Equals("Tuesday", comparisonType): + result = 1; + return true; + case { } when value.Equals("Thursday", comparisonType): + result = 3; + return true; + } + break; + case 'W': + case 'w': + switch (value) + { + case { } when value.Equals("Wednesday", comparisonType): + result = 2; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -192,15 +303,8 @@ public static bool TryParse( StringComparison comparisonType, out NestedInClass.MyEnum3 result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (NestedInClass.MyEnum3)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -219,7 +323,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out NestedInClass.MyEnum3 result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -234,7 +339,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static NestedInClass.MyEnum3? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out NestedInClass.MyEnum3 result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum3?)result : null; } /// @@ -251,7 +356,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static NestedInClass.MyEnum3? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out NestedInClass.MyEnum3 result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (NestedInClass.MyEnum3?)result : null; } public static bool TryCreateFromDisplayShortName( @@ -422,11 +527,5 @@ public static string[] GetNames() "Sunday", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Validation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Validation.g.cs index 23fca72..fdd07d5 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Validation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.MyEnum3Validation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class MyEnum3Validation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodEnumInfo.g.cs index d148caf..b1bd745 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodEnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodEnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class PaymentMethodMetadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 6; /// The string representation of name. @@ -36,7 +37,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 6; /// The UTF-8 representation of name. @@ -55,246 +56,39 @@ public static partial class Utf8Name /// Provides constant values for serialized members values. public static partial class SerializedValue { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by serializing a value to string, based on defined members. public const int MaxCharsLength = 11; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Credit = "Credit card"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Debit = "Debit card"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Cash = "Cash"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Cheque = "Cheque"; } - /// Provides static values for UTF-8 encoded members serialized values. + /// Provides static values for UTF-8 encoded serialized members values. public static partial class Utf8SerializedValue { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by serializing a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 11; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Credit => new byte[11] { 67, 114, 101, 100, 105, 116, 32, 99, 97, 114, 100 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Debit => new byte[10] { 68, 101, 98, 105, 116, 32, 99, 97, 114, 100 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Cash => new byte[4] { 67, 97, 115, 104 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Cheque => new byte[6] { 67, 104, 101, 113, 117, 101 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 0 => 6, - 1 => 5, - 2 => 4, - 3 => 6, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 0 => "Credit", - 1 => "Debit", - 2 => "Cash", - 3 => "Cheque", - _ => null - }; - } - } - - /// Provides support for formatting serialized values. - internal sealed partial class SerializationStringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static SerializationStringFormatter Instance = new SerializationStringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 0 => 11, - 1 => 10, - 2 => 4, - 3 => 6, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 0 => "Credit card", - 1 => "Debit card", - 2 => "Cash", - 3 => "Cheque", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser, IEnumDescriptionParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("Credit", comparisonType): - result = 0; - return true; - case { } when value.Equals("Cash", comparisonType): - result = 2; - return true; - case { } when value.Equals("Cheque", comparisonType): - result = 3; - return true; - } - goto default; - case 'D': - case 'd': - switch (value) - { - case { } when value.Equals("Debit", comparisonType): - result = 1; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - - /// - public bool TryParseDescription(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - switch (value) - { - case { } s when s.Equals("The payment by using physical cash", comparisonType): - result = 2; - return true; - default: - result = default; - return false; - } - } - } - - /// Provides support for parsing serialized values. - internal sealed partial class SerializationStringParser : IEnumParser - { - /// Gets the singleton instance of the class. - public static SerializationStringParser Instance = new SerializationStringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("Credit card", comparisonType): - result = 0; - return true; - case { } when value.Equals("Cash", comparisonType): - result = 2; - return true; - case { } when value.Equals("Cheque", comparisonType): - result = 3; - return true; - } - goto default; - case 'D': - case 'd': - switch (value) - { - case { } when value.Equals("Debit card", comparisonType): - result = 1; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodExtensions.g.cs index ec265a0..869ef48 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodExtensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodExtensions.g.cs @@ -11,17 +11,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class PaymentMethodExtensions { - private static readonly PaymentMethodMetadata.StringFormatter s_stringFormatter = PaymentMethodMetadata.StringFormatter.Instance; - private static readonly PaymentMethodMetadata.SerializationStringFormatter s_serializationStringFormatter = PaymentMethodMetadata.SerializationStringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this PaymentMethod value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return GetNameInlined((int)value) + ?? ((int)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -29,14 +27,46 @@ public static string ToStringFast(this PaymentMethod value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this PaymentMethod value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return GetNameLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this PaymentMethod value) { - return PaymentMethodValidation.IsDefined(value); + return (int)value switch + { + 0 => true, + 1 => true, + 2 => true, + 3 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + 0 => 6, + 1 => 5, + 2 => 4, + 3 => 6, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + 0 => "Credit", + 1 => "Debit", + 2 => "Cash", + 3 => "Cheque", + _ => null + }; } /// Adds two enumerations and replaces the first integer with the sum, as an atomic operation. @@ -95,12 +125,38 @@ public static PaymentMethod InterlockedExchange(this ref PaymentMethod location, public static string ToEnumMemberValue(this PaymentMethod value) { - return EnumStringFormatter.GetString((int)value, s_serializationStringFormatter); + return GetEnumMemberValueInlined((int)value) + ?? ((int)value).ToString(); } public static int GetEnumMemberValueStringLength(this PaymentMethod value) { - return EnumStringFormatter.GetStringLength((int)value, s_serializationStringFormatter); + return GetEnumMemberValueLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); + } + + private static int? GetEnumMemberValueLengthInlined(int value) + { + return value switch + { + 0 => 11, + 1 => 10, + 2 => 4, + 3 => 6, + _ => null + }; + } + + private static string? GetEnumMemberValueInlined(int value) + { + return value switch + { + 0 => "Credit card", + 1 => "Debit card", + 2 => "Cash", + 3 => "Cheque", + _ => null + }; } public static string? GetDescription(this PaymentMethod value) diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodFactory.g.cs index cf604d8..86eedbe 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodFactory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodFactory.g.cs @@ -12,12 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class PaymentMethodFactory { - private static readonly PaymentMethodMetadata.StringParser s_stringParser = PaymentMethodMetadata.StringParser.Instance; - private static readonly PaymentMethodMetadata.SerializationStringParser s_serializationStringParser = PaymentMethodMetadata.SerializationStringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -29,9 +26,9 @@ public static partial class PaymentMethodFactory /// is empty or does not represent a valid value. public static PaymentMethod Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (PaymentMethod)result; } /// @@ -44,8 +41,8 @@ public static PaymentMethod Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static PaymentMethod Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (PaymentMethod)result; } /// @@ -60,8 +57,8 @@ public static PaymentMethod Parse(ReadOnlySpan value, bool ignoreCase = fa public static PaymentMethod? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (PaymentMethod)result; } /// @@ -78,7 +75,8 @@ public static PaymentMethod Parse(ReadOnlySpan value, bool ignoreCase = fa /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out PaymentMethod result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -94,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out PaymentMethod result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -109,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out PaymentMethod /// public static PaymentMethod? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out PaymentMethod result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (PaymentMethod?)result : null; } /// @@ -126,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out PaymentMethod /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out PaymentMethod result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -142,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Payme /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out PaymentMethod result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -157,21 +158,103 @@ public static bool TryParse(ReadOnlySpan value, out PaymentMethod result) /// public static PaymentMethod? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out PaymentMethod result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (PaymentMethod?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out PaymentMethod result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (PaymentMethod)number; - return true; + switch (value[0]) + { + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("Credit", comparisonType): + result = 0; + return true; + case { } when value.Equals("Cash", comparisonType): + result = 2; + return true; + case { } when value.Equals("Cheque", comparisonType): + result = 3; + return true; + } + break; + case 'D': + case 'd': + switch (value) + { + case { } when value.Equals("Debit", comparisonType): + result = 1; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -193,15 +276,8 @@ public static bool TryParse( StringComparison comparisonType, out PaymentMethod result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (PaymentMethod)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -220,7 +296,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out PaymentMethod result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -235,7 +312,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static PaymentMethod? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out PaymentMethod result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (PaymentMethod?)result : null; } /// @@ -252,7 +329,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static PaymentMethod? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out PaymentMethod result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (PaymentMethod?)result : null; } /// @@ -265,9 +342,9 @@ public static bool TryParseIgnoreCase( /// is empty or does not represent a valid value. public static PaymentMethod ParseFromEnumMemberValue(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (PaymentMethod)result; } /// @@ -279,8 +356,8 @@ public static PaymentMethod ParseFromEnumMemberValue(string value, bool ignoreCa /// is empty or does not represent a valid value. public static PaymentMethod ParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (PaymentMethod)result; } /// @@ -294,8 +371,8 @@ public static PaymentMethod ParseFromEnumMemberValue(ReadOnlySpan value, b public static PaymentMethod? ParseFromEnumMemberValueOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (PaymentMethod)result; } /// @@ -312,7 +389,8 @@ public static PaymentMethod ParseFromEnumMemberValue(ReadOnlySpan value, b /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, bool ignoreCase, out PaymentMethod result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -328,7 +406,8 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, out PaymentMethod result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -342,7 +421,7 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// public static PaymentMethod? TryParseFromEnumMemberValue(string? value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out PaymentMethod result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (PaymentMethod?)result : null; } /// @@ -359,7 +438,8 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, out PaymentMethod result) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -375,7 +455,8 @@ public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ig /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out PaymentMethod result) { - return TryParseFromEnumMemberValue(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -389,25 +470,103 @@ public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out Pay /// public static PaymentMethod? TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out PaymentMethod result) ? result : null; + return TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (PaymentMethod?)result : null; + } + + private static bool TryParseEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericEnumMemberValue(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericEnumMemberValue(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; } - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out PaymentMethod result) + private static bool TryParseNonNumericEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) { - return TryParseFromEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure, out result); + bool success = TryParseSingleEnumMemberValue(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out PaymentMethod result) + private static bool TryParseSingleEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, out int result) { - bool success = EnumStringParser.TryParse(value, s_serializationStringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (PaymentMethod)number; - return true; + switch (value[0]) + { + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("Credit card", comparisonType): + result = 0; + return true; + case { } when value.Equals("Cash", comparisonType): + result = 2; + return true; + case { } when value.Equals("Cheque", comparisonType): + result = 3; + return true; + } + break; + case 'D': + case 'd': + switch (value) + { + case { } when value.Equals("Debit card", comparisonType): + result = 1; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -429,7 +588,8 @@ public static bool TryParseFromEnumMemberValue( StringComparison comparisonType, out PaymentMethod result) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -446,71 +606,119 @@ public static bool TryParseFromEnumMemberValue( [Obsolete("Use TryParseFromEnumMemberValue overload with 'ignoreCase' parameter")] public static PaymentMethod? TryParseFromEnumMemberValue(string? value, StringComparison comparisonType) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out PaymentMethod result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (PaymentMethod?)result : null; } public static PaymentMethod CreateFromDescription(string description, StringComparison comparisonType = StringComparison.Ordinal) { - if (description is null) ThrowArgumentNullException(nameof(description)); - TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); - return result; + if (description is null) ThrowHelper.ThrowArgumentNullException(nameof(description)); + TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); + return (PaymentMethod)result; } public static PaymentMethod CreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal) { - TryCreateFromDescription(description, comparisonType, throwOnFailure: true, out var result); - return result; + TryParseDescription(description, comparisonType, throwOnFailure: true, out var result); + return (PaymentMethod)result; } [return: NotNullIfNotNull("description")] public static PaymentMethod? CreateFromDescriptionOrNull(string? description, StringComparison comparisonType = StringComparison.Ordinal) { if (description is null) return null; - TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); - return result; + TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: true, out var result); + return (PaymentMethod)result; } public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, StringComparison comparisonType, out PaymentMethod result) { - return TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } public static bool TryCreateFromDescription([NotNullWhen(true)] string? description, out PaymentMethod result) { - return TryCreateFromDescription(description.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } public static PaymentMethod? TryCreateFromDescription(string? description, StringComparison comparisonType = StringComparison.Ordinal) { - return TryCreateFromDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out PaymentMethod result) ? result : null; + return TryParseDescription(description.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (PaymentMethod?)result : null; } public static bool TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType, out PaymentMethod result) { - return TryCreateFromDescription(description, comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description, comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } public static bool TryCreateFromDescription(ReadOnlySpan description, out PaymentMethod result) { - return TryCreateFromDescription(description, StringComparison.Ordinal, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseDescription(description, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } public static PaymentMethod? TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType = StringComparison.Ordinal) { - return TryCreateFromDescription(description, comparisonType, throwOnFailure: false, out PaymentMethod result) ? result : null; + return TryParseDescription(description, comparisonType, throwOnFailure: false, out var result) ? (PaymentMethod?)result : null; } - private static bool TryCreateFromDescription(ReadOnlySpan description, StringComparison comparisonType, bool throwOnFailure, out PaymentMethod result) + private static bool TryParseDescription(ReadOnlySpan description, StringComparison comparisonType, bool throwOnFailure, out int result) { - bool success = EnumStringParser.TryParseDescription(description, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (!description.IsEmpty) + { + return TryParseNonNumericDescription(description, comparisonType, throwOnFailure, out result); + } + + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(description)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericDescription(ReadOnlySpan description, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleDescription(description, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(description, nameof(description)); + } + + return false; + } + + private static bool TryParseSingleDescription(ReadOnlySpan value, StringComparison comparisonType, out int result) + { + if (value.IsEmpty) { result = 0; return false; } - result = (PaymentMethod)number; - return true; + switch (value[0]) + { + case 'T': + case 't': + switch (value) + { + case { } when value.Equals("The payment by using physical cash", comparisonType): + result = 2; + return true; + } + break; + } + + result = 0; + return false; } public static bool TryCreateFromDisplayShortName( @@ -605,11 +813,5 @@ public static string[] GetNames() "Cheque", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodValidation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodValidation.g.cs index c334982..6dd4edd 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodValidation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.PaymentMethodValidation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class PaymentMethodValidation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonEnumInfo.g.cs deleted file mode 100644 index a258781..0000000 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonEnumInfo.g.cs +++ /dev/null @@ -1,120 +0,0 @@ -// -#nullable enable - -using System; -using System.Runtime.CompilerServices; -using Raiqub.Generators.EnumUtilities.Formatters; -using Raiqub.Generators.EnumUtilities.Parsers; - -#pragma warning disable CS1591 // publicly visible type or member must be documented - -namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models -{ - [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] - public static partial class SeasonMetadata - { - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 1 => 6, - 2 => 6, - 3 => 6, - 4 => 6, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 1 => "Spring", - 2 => "Summer", - 3 => "Autumn", - 4 => "Winter", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'S': - case 's': - switch (value) - { - case { } when value.Equals("Spring", comparisonType): - result = 1; - return true; - case { } when value.Equals("Summer", comparisonType): - result = 2; - return true; - } - goto default; - case 'A': - case 'a': - switch (value) - { - case { } when value.Equals("Autumn", comparisonType): - result = 3; - return true; - } - goto default; - case 'W': - case 'w': - switch (value) - { - case { } when value.Equals("Winter", comparisonType): - result = 4; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } - } -} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonExtensions.g.cs new file mode 100644 index 0000000..9df1db6 --- /dev/null +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonExtensions.g.cs @@ -0,0 +1,56 @@ +// +#nullable enable + +using System; +using System.Runtime.CompilerServices; +using System.Threading; +using Raiqub.Generators.EnumUtilities.Formatters; + +#pragma warning disable CS1591 // publicly visible type or member must be documented + +namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] + public static partial class SeasonExtensions + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? ToJsonString(this Season value) + { + return GetJsonStringInlined((int)value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int? GetJsonStringLength(this Season value) + { + return GetJsonStringLengthInlined((int)value); + } + + private static int? GetJsonStringLengthInlined(int value) + { + return value switch + { + 0 => 1, + 1 => 2, + 2 => 2, + 3 => 2, + 4 => 1, + _ => null + }; + } + + private static string? GetJsonStringInlined(int value) + { + return value switch + { + 0 => "0", + 1 => "🌱", + 2 => "☀️", + 3 => "🍂", + 4 => "⛄", + _ => null + }; + } + } +} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonFactory.g.cs new file mode 100644 index 0000000..c3dc49b --- /dev/null +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonFactory.g.cs @@ -0,0 +1,235 @@ +// +#nullable enable + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Runtime.CompilerServices; +using Raiqub.Generators.EnumUtilities.Parsers; + +#pragma warning disable CS1591 // publicly visible type or member must be documented + +namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models +{ + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] + public static partial class SeasonFactory + { + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value. Note that this value need not be a member of the Season enumeration. + /// is . + /// is empty or does not represent a valid value. + public static Season ParseJsonString(string value, bool ignoreCase = false) + { + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (Season)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value. Note that this value need not be a member of the Season enumeration. + /// is empty or does not represent a valid value. + public static Season ParseJsonString(ReadOnlySpan value, bool ignoreCase = false) + { + TryParseJsonString(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (Season)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// The value represented by the specified serialized value or null. Note that this value need not be a member of the Season enumeration. + /// is empty or does not represent a valid value. + [return: NotNullIfNotNull("value")] + public static Season? ParseJsonStringOrNull(string? value, bool ignoreCase = false) + { + if (value is null) return null; + TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (Season)result; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// When this method returns, result contains an object of type Season whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of Season. Note that this value need not be a member of the Season enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString([NotNullWhen(true)] string? value, bool ignoreCase, out Season result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// + /// When this method returns, result contains an object of type Season whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of Season. Note that this value need not be a member of the Season enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString([NotNullWhen(true)] string? value, out Season result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// Contains an object of type Season whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains a null value. + /// + public static Season? TryParseJsonString(string? value, bool ignoreCase = false) + { + return TryParseJsonString(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (Season?)result : null; + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// When this method returns, result contains an object of type Season whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of Season. Note that this value need not be a member of the Season enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString(ReadOnlySpan value, bool ignoreCase, out Season result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// + /// When this method returns, result contains an object of type Season whose value is represented by a + /// serialized JSON value if the parse operation succeeds. If the parse operation fails, result contains the default + /// value of the underlying type of Season. Note that this value need not be a member of the Season enumeration. + /// + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParseJsonString(ReadOnlySpan value, out Season result) + { + Unsafe.SkipInit(out result); + return TryParseJsonString(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); + } + + /// + /// Converts the string representation of the serialized JSON value to an equivalent enumerated object. + /// + /// The string representation of the enumeration serialized JSON value to convert. + /// to ignore case; to regard case. + /// + /// Contains an object of type Season whose value is represented by value if the parse operation succeeds. + /// If the parse operation fails, result contains a null value. + /// + public static Season? TryParseJsonString(ReadOnlySpan value, bool ignoreCase = false) + { + return TryParseJsonString(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (Season?)result : null; + } + + private static bool TryParseJsonString(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + return TryParseNonNumericJsonString(value, comparisonType, throwOnFailure, out result); + } + + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericJsonString(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleJsonString(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; + } + + private static bool TryParseSingleJsonString(ReadOnlySpan value, StringComparison comparisonType, out int result) + { + if (value.IsEmpty) + { + result = 0; + return false; + } + + switch (value[0]) + { + case '☀': + switch (value) + { + case { } when value.Equals("☀️", comparisonType): + result = 2; + return true; + } + break; + case '⛄': + switch (value) + { + case { } when value.Equals("⛄", comparisonType): + result = 4; + return true; + } + break; + case '\ud83c': + switch (value) + { + case { } when value.Equals("🌱", comparisonType): + result = 1; + return true; + case { } when value.Equals("🍂", comparisonType): + result = 3; + return true; + } + break; + } + + result = 0; + return false; + } + } +} diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonJsonConverter.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonJsonConverter.g.cs index 50383bd..6466c49 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonJsonConverter.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SeasonJsonConverter.g.cs @@ -2,6 +2,7 @@ #nullable enable using System; +using System.Buffers; using System.Text.Json; using System.Text.Json.Serialization; using Raiqub.Generators.EnumUtilities.Formatters; @@ -12,106 +13,76 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public sealed class SeasonJsonConverter : JsonConverter { - private const int MaxBytesLength = 12; - private const int MaxCharsLength = 2; - - private static readonly SeasonMetadata.StringFormatter s_stringFormatter = SeasonMetadata.StringFormatter.Instance; - private static readonly SeasonMetadata.StringParser s_stringParser = SeasonMetadata.StringParser.Instance; + private const int MaxCharStack = 256; public override Season Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) - return (Season)ReadFromString(ref reader); + return ReadFromString(ref reader); if (reader.TokenType == JsonTokenType.Number) return (Season)ReadFromNumber(ref reader); throw new JsonException(); } - #if NET7_0_OR_GREATER - public override void Write(Utf8JsonWriter writer, Season value, JsonSerializerOptions options) { - switch ((int)value) + string? jsonString = value.ToJsonString(); + if (jsonString is not null) + { + writer.WriteStringValue(jsonString); + } + else { - case 1: - writer.WriteStringValue("🌱"u8); - break; - case 2: - writer.WriteStringValue("☀️"u8); - break; - case 3: - writer.WriteStringValue("🍂"u8); - break; - case 4: - writer.WriteStringValue("⛄"u8); - break; - default: - string strValue = EnumStringFormatter.GetString((int)value, s_stringFormatter); - writer.WriteStringValue(strValue); - break; + writer.WriteNumberValue((int)value); } } - private int ReadFromString(ref Utf8JsonReader reader) + #if NET7_0_OR_GREATER + + private Season ReadFromString(ref Utf8JsonReader reader) { int length = reader.HasValueSequence ? checked((int)reader.ValueSequence.Length) : reader.ValueSpan.Length; - if (length > MaxBytesLength) - throw new JsonException(); - Span name = stackalloc char[MaxBytesLength]; - int charsWritten = reader.CopyString(name); - name = name.Slice(0, charsWritten); - - return name switch + char[]? rented = null; + Span name = length <= MaxCharStack ? stackalloc char[MaxCharStack] : (rented = ArrayPool.Shared.Rent(length)); + try { - "🌱" => 1, - "☀️" => 2, - "🍂" => 3, - "⛄" => 4, - _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out int result) ? result : throw new JsonException() - }; - } + int charsWritten = reader.CopyString(name); + name = name.Slice(0, charsWritten); - #else + bool isParsed = SeasonFactory.TryParseJsonString(name, ignoreCase: false, out Season result); + if (!isParsed) + { + throw new JsonException(); + } - public override void Write(Utf8JsonWriter writer, Season value, JsonSerializerOptions options) - { - switch ((int)value) + return result; + } + finally { - case 1: - writer.WriteStringValue("🌱"); - break; - case 2: - writer.WriteStringValue("☀️"); - break; - case 3: - writer.WriteStringValue("🍂"); - break; - case 4: - writer.WriteStringValue("⛄"); - break; - default: - string strValue = EnumStringFormatter.GetString((int)value, s_stringFormatter); - writer.WriteStringValue(strValue); - break; + if (rented != null) + { + ArrayPool.Shared.Return(rented); + } } } - private int ReadFromString(ref Utf8JsonReader reader) + #else + + private Season ReadFromString(ref Utf8JsonReader reader) { var name = reader.GetString(); - return name switch + bool isParsed = SeasonFactory.TryParseJsonString(name, ignoreCase: false, out Season result); + if (!isParsed) { - "🌱" => 1, - "☀️" => 2, - "🍂" => 3, - "⛄" => 4, - _ => EnumStringParser.TryParse(name, s_stringParser, StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out int result) ? result : throw new JsonException() - }; + throw new JsonException(); + } + + return result; } #endif diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesEnumInfo.g.cs index e4dd3ce..2444cca 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesEnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesEnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class SlimCategoriesMetadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 11; /// The string representation of name. @@ -42,7 +43,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 11; /// The UTF-8 representation of name. @@ -63,124 +64,5 @@ public static partial class Utf8Name /// The UTF-8 representation of name. public static ReadOnlySpan Fashion => new byte[7] { 70, 97, 115, 104, 105, 111, 110 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(byte value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(byte value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(byte value) - { - return value switch - { - 0 => 11, - 1 => 4, - 2 => 10, - 3 => 4, - 4 => 10, - 5 => 7, - _ => null - }; - } - - /// - public string? TryGetStringForMember(byte value) - { - return value switch - { - 0 => "Electronics", - 1 => "Food", - 2 => "Automotive", - 3 => "Arts", - 4 => "BeautyCare", - 5 => "Fashion", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte BitwiseOr(byte value1, byte value2) => unchecked((byte)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out byte result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out byte result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'E': - case 'e': - switch (value) - { - case { } when value.Equals("Electronics", comparisonType): - result = 0; - return true; - } - goto default; - case 'F': - case 'f': - switch (value) - { - case { } when value.Equals("Food", comparisonType): - result = 1; - return true; - case { } when value.Equals("Fashion", comparisonType): - result = 5; - return true; - } - goto default; - case 'A': - case 'a': - switch (value) - { - case { } when value.Equals("Automotive", comparisonType): - result = 2; - return true; - case { } when value.Equals("Arts", comparisonType): - result = 3; - return true; - } - goto default; - case 'B': - case 'b': - switch (value) - { - case { } when value.Equals("BeautyCare", comparisonType): - result = 4; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesExtensions.g.cs index 46fccc9..2a9896b 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesExtensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesExtensions.g.cs @@ -10,16 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class SlimCategoriesExtensions { - private static readonly SlimCategoriesMetadata.StringFormatter s_stringFormatter = SlimCategoriesMetadata.StringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this SlimCategories value) { - return EnumStringFormatter.GetString((byte)value, s_stringFormatter); + return GetNameInlined((byte)value) + ?? ((byte)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -27,14 +26,52 @@ public static string ToStringFast(this SlimCategories value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this SlimCategories value) { - return EnumStringFormatter.GetStringLength((byte)value, s_stringFormatter); + return GetNameLengthInlined((byte)value) + ?? EnumNumericFormatter.GetStringLength((byte)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this SlimCategories value) { - return SlimCategoriesValidation.IsDefined(value); + return (byte)value switch + { + 0 => true, + 1 => true, + 2 => true, + 3 => true, + 4 => true, + 5 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(byte value) + { + return value switch + { + 0 => 11, + 1 => 4, + 2 => 10, + 3 => 4, + 4 => 10, + 5 => 7, + _ => null + }; + } + + private static string? GetNameInlined(byte value) + { + return value switch + { + 0 => "Electronics", + 1 => "Food", + 2 => "Automotive", + 3 => "Arts", + 4 => "BeautyCare", + 5 => "Fashion", + _ => null + }; } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesFactory.g.cs index 19b05c3..4c0b1b0 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesFactory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesFactory.g.cs @@ -12,11 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class SlimCategoriesFactory { - private static readonly SlimCategoriesMetadata.StringParser s_stringParser = SlimCategoriesMetadata.StringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -28,9 +26,9 @@ public static partial class SlimCategoriesFactory /// is empty or does not represent a valid value. public static SlimCategories Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (SlimCategories)result; } /// @@ -43,8 +41,8 @@ public static SlimCategories Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static SlimCategories Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (SlimCategories)result; } /// @@ -59,8 +57,8 @@ public static SlimCategories Parse(ReadOnlySpan value, bool ignoreCase = f public static SlimCategories? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (SlimCategories)result; } /// @@ -77,7 +75,8 @@ public static SlimCategories Parse(ReadOnlySpan value, bool ignoreCase = f /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out SlimCategories result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -93,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out SlimCategories result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -108,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out SlimCategorie /// public static SlimCategories? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out SlimCategories result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (SlimCategories?)result : null; } /// @@ -125,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out SlimCategorie /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out SlimCategories result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -141,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out SlimC /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out SlimCategories result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -156,21 +158,121 @@ public static bool TryParse(ReadOnlySpan value, out SlimCategories result) /// public static SlimCategories? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out SlimCategories result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (SlimCategories?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out byte result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out byte result) + { + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out SlimCategories result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out byte result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out byte number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (SlimCategories)number; - return true; + switch (value[0]) + { + case 'A': + case 'a': + switch (value) + { + case { } when value.Equals("Automotive", comparisonType): + result = 2; + return true; + case { } when value.Equals("Arts", comparisonType): + result = 3; + return true; + } + break; + case 'B': + case 'b': + switch (value) + { + case { } when value.Equals("BeautyCare", comparisonType): + result = 4; + return true; + } + break; + case 'E': + case 'e': + switch (value) + { + case { } when value.Equals("Electronics", comparisonType): + result = 0; + return true; + } + break; + case 'F': + case 'f': + switch (value) + { + case { } when value.Equals("Food", comparisonType): + result = 1; + return true; + case { } when value.Equals("Fashion", comparisonType): + result = 5; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -192,15 +294,8 @@ public static bool TryParse( StringComparison comparisonType, out SlimCategories result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out byte number); - if (!success) - { - result = 0; - return false; - } - - result = (SlimCategories)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -219,7 +314,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out SlimCategories result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -234,7 +330,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static SlimCategories? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out SlimCategories result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (SlimCategories?)result : null; } /// @@ -251,7 +347,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static SlimCategories? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out SlimCategories result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (SlimCategories?)result : null; } /// Retrieves an array of the values of the constants in the SlimCategories enumeration. @@ -283,11 +379,5 @@ public static string[] GetNames() "Fashion", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesValidation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesValidation.g.cs index 76559f8..f579797 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesValidation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.SlimCategoriesValidation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class SlimCategoriesValidation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeEnumInfo.g.cs index a908337..1bc7b04 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeEnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeEnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class StatusCodeMetadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 14; /// The string representation of name. @@ -57,7 +58,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 14; /// The UTF-8 representation of name. @@ -97,428 +98,81 @@ public static partial class Utf8Name /// Provides constant values for serialized members values. public static partial class SerializedValue { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by serializing a value to string, based on defined members. public const int MaxCharsLength = 14; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Unknown = "Unknown"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Success = "Success"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Error = "Error"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string NotFound = "Not Found"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Timeout = "Timeout"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Unauthorized = "Unauthorized"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Forbidden = "Forbidden"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Conflict = "Conflict"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Gone = "Gone"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string InvalidRequest = "InvalidRequest"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string ServerError = "ServerError"; } - /// Provides static values for UTF-8 encoded members serialized values. + /// Provides static values for UTF-8 encoded serialized members values. public static partial class Utf8SerializedValue { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by serializing a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 14; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Unknown => new byte[7] { 85, 110, 107, 110, 111, 119, 110 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Success => new byte[7] { 83, 117, 99, 99, 101, 115, 115 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Error => new byte[5] { 69, 114, 114, 111, 114 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan NotFound => new byte[9] { 78, 111, 116, 32, 70, 111, 117, 110, 100 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Timeout => new byte[7] { 84, 105, 109, 101, 111, 117, 116 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Unauthorized => new byte[12] { 85, 110, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Forbidden => new byte[9] { 70, 111, 114, 98, 105, 100, 100, 101, 110 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Conflict => new byte[8] { 67, 111, 110, 102, 108, 105, 99, 116 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Gone => new byte[4] { 71, 111, 110, 101 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan InvalidRequest => new byte[14] { 73, 110, 118, 97, 108, 105, 100, 82, 101, 113, 117, 101, 115, 116 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan ServerError => new byte[11] { 83, 101, 114, 118, 101, 114, 69, 114, 114, 111, 114 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - -1 => 7, - 0 => 7, - -2 => 5, - -3 => 8, - -4 => 7, - -5 => 12, - -6 => 9, - -7 => 8, - -8 => 4, - -9 => 14, - -10 => 11, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - -1 => "Unknown", - 0 => "Success", - -2 => "Error", - -3 => "NotFound", - -4 => "Timeout", - -5 => "Unauthorized", - -6 => "Forbidden", - -7 => "Conflict", - -8 => "Gone", - -9 => "InvalidRequest", - -10 => "ServerError", - _ => null - }; - } - } - - /// Provides support for formatting serialized values. - internal sealed partial class SerializationStringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static SerializationStringFormatter Instance = new SerializationStringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - -1 => 7, - 0 => 7, - -2 => 5, - -3 => 9, - -4 => 7, - -5 => 12, - -6 => 9, - -7 => 8, - -8 => 4, - -9 => 14, - -10 => 11, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - -1 => "Unknown", - 0 => "Success", - -2 => "Error", - -3 => "Not Found", - -4 => "Timeout", - -5 => "Unauthorized", - -6 => "Forbidden", - -7 => "Conflict", - -8 => "Gone", - -9 => "InvalidRequest", - -10 => "ServerError", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'U': - case 'u': - switch (value) - { - case { } when value.Equals("Unknown", comparisonType): - result = -1; - return true; - case { } when value.Equals("Unauthorized", comparisonType): - result = -5; - return true; - } - goto default; - case 'S': - case 's': - switch (value) - { - case { } when value.Equals("Success", comparisonType): - result = 0; - return true; - case { } when value.Equals("ServerError", comparisonType): - result = -10; - return true; - } - goto default; - case 'E': - case 'e': - switch (value) - { - case { } when value.Equals("Error", comparisonType): - result = -2; - return true; - } - goto default; - case 'N': - case 'n': - switch (value) - { - case { } when value.Equals("NotFound", comparisonType): - result = -3; - return true; - } - goto default; - case 'T': - case 't': - switch (value) - { - case { } when value.Equals("Timeout", comparisonType): - result = -4; - return true; - } - goto default; - case 'F': - case 'f': - switch (value) - { - case { } when value.Equals("Forbidden", comparisonType): - result = -6; - return true; - } - goto default; - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("Conflict", comparisonType): - result = -7; - return true; - } - goto default; - case 'G': - case 'g': - switch (value) - { - case { } when value.Equals("Gone", comparisonType): - result = -8; - return true; - } - goto default; - case 'I': - case 'i': - switch (value) - { - case { } when value.Equals("InvalidRequest", comparisonType): - result = -9; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } - - /// Provides support for parsing serialized values. - internal sealed partial class SerializationStringParser : IEnumParser - { - /// Gets the singleton instance of the class. - public static SerializationStringParser Instance = new SerializationStringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'U': - case 'u': - switch (value) - { - case { } when value.Equals("Unknown", comparisonType): - result = -1; - return true; - case { } when value.Equals("Unauthorized", comparisonType): - result = -5; - return true; - } - goto default; - case 'S': - case 's': - switch (value) - { - case { } when value.Equals("Success", comparisonType): - result = 0; - return true; - case { } when value.Equals("ServerError", comparisonType): - result = -10; - return true; - } - goto default; - case 'E': - case 'e': - switch (value) - { - case { } when value.Equals("Error", comparisonType): - result = -2; - return true; - } - goto default; - case 'N': - case 'n': - switch (value) - { - case { } when value.Equals("Not Found", comparisonType): - result = -3; - return true; - } - goto default; - case 'T': - case 't': - switch (value) - { - case { } when value.Equals("Timeout", comparisonType): - result = -4; - return true; - } - goto default; - case 'F': - case 'f': - switch (value) - { - case { } when value.Equals("Forbidden", comparisonType): - result = -6; - return true; - } - goto default; - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("Conflict", comparisonType): - result = -7; - return true; - } - goto default; - case 'G': - case 'g': - switch (value) - { - case { } when value.Equals("Gone", comparisonType): - result = -8; - return true; - } - goto default; - case 'I': - case 'i': - switch (value) - { - case { } when value.Equals("InvalidRequest", comparisonType): - result = -9; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeExtensions.g.cs index bb2aa87..56229f6 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeExtensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeExtensions.g.cs @@ -11,17 +11,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class StatusCodeExtensions { - private static readonly StatusCodeMetadata.StringFormatter s_stringFormatter = StatusCodeMetadata.StringFormatter.Instance; - private static readonly StatusCodeMetadata.SerializationStringFormatter s_serializationStringFormatter = StatusCodeMetadata.SerializationStringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this StatusCode value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return GetNameInlined((int)value) + ?? ((int)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -29,14 +27,67 @@ public static string ToStringFast(this StatusCode value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this StatusCode value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return GetNameLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this StatusCode value) { - return StatusCodeValidation.IsDefined(value); + return (int)value switch + { + -1 => true, + 0 => true, + -2 => true, + -3 => true, + -4 => true, + -5 => true, + -6 => true, + -7 => true, + -8 => true, + -9 => true, + -10 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + -1 => 7, + 0 => 7, + -2 => 5, + -3 => 8, + -4 => 7, + -5 => 12, + -6 => 9, + -7 => 8, + -8 => 4, + -9 => 14, + -10 => 11, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + -1 => "Unknown", + 0 => "Success", + -2 => "Error", + -3 => "NotFound", + -4 => "Timeout", + -5 => "Unauthorized", + -6 => "Forbidden", + -7 => "Conflict", + -8 => "Gone", + -9 => "InvalidRequest", + -10 => "ServerError", + _ => null + }; } /// Adds two enumerations and replaces the first integer with the sum, as an atomic operation. @@ -95,12 +146,52 @@ public static StatusCode InterlockedExchange(this ref StatusCode location, Statu public static string ToEnumMemberValue(this StatusCode value) { - return EnumStringFormatter.GetString((int)value, s_serializationStringFormatter); + return GetEnumMemberValueInlined((int)value) + ?? ((int)value).ToString(); } public static int GetEnumMemberValueStringLength(this StatusCode value) { - return EnumStringFormatter.GetStringLength((int)value, s_serializationStringFormatter); + return GetEnumMemberValueLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); + } + + private static int? GetEnumMemberValueLengthInlined(int value) + { + return value switch + { + -1 => 7, + 0 => 7, + -2 => 5, + -3 => 9, + -4 => 7, + -5 => 12, + -6 => 9, + -7 => 8, + -8 => 4, + -9 => 14, + -10 => 11, + _ => null + }; + } + + private static string? GetEnumMemberValueInlined(int value) + { + return value switch + { + -1 => "Unknown", + 0 => "Success", + -2 => "Error", + -3 => "Not Found", + -4 => "Timeout", + -5 => "Unauthorized", + -6 => "Forbidden", + -7 => "Conflict", + -8 => "Gone", + -9 => "InvalidRequest", + -10 => "ServerError", + _ => null + }; } public static string GetDisplayShortName(this StatusCode value) diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeFactory.g.cs index c4d0a04..ef345c9 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeFactory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeFactory.g.cs @@ -12,12 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class StatusCodeFactory { - private static readonly StatusCodeMetadata.StringParser s_stringParser = StatusCodeMetadata.StringParser.Instance; - private static readonly StatusCodeMetadata.SerializationStringParser s_serializationStringParser = StatusCodeMetadata.SerializationStringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -29,9 +26,9 @@ public static partial class StatusCodeFactory /// is empty or does not represent a valid value. public static StatusCode Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (StatusCode)result; } /// @@ -44,8 +41,8 @@ public static StatusCode Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static StatusCode Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (StatusCode)result; } /// @@ -60,8 +57,8 @@ public static StatusCode Parse(ReadOnlySpan value, bool ignoreCase = false public static StatusCode? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (StatusCode)result; } /// @@ -78,7 +75,8 @@ public static StatusCode Parse(ReadOnlySpan value, bool ignoreCase = false /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out StatusCode result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -94,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out StatusCode result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -109,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out StatusCode re /// public static StatusCode? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out StatusCode result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (StatusCode?)result : null; } /// @@ -126,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out StatusCode re /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out StatusCode result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -142,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out Statu /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out StatusCode result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -157,21 +158,166 @@ public static bool TryParse(ReadOnlySpan value, out StatusCode result) /// public static StatusCode? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out StatusCode result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (StatusCode?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out StatusCode result) + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; + } + + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) + { + if (value.IsEmpty) { result = 0; return false; } - result = (StatusCode)number; - return true; + switch (value[0]) + { + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("Conflict", comparisonType): + result = -7; + return true; + } + break; + case 'E': + case 'e': + switch (value) + { + case { } when value.Equals("Error", comparisonType): + result = -2; + return true; + } + break; + case 'F': + case 'f': + switch (value) + { + case { } when value.Equals("Forbidden", comparisonType): + result = -6; + return true; + } + break; + case 'G': + case 'g': + switch (value) + { + case { } when value.Equals("Gone", comparisonType): + result = -8; + return true; + } + break; + case 'I': + case 'i': + switch (value) + { + case { } when value.Equals("InvalidRequest", comparisonType): + result = -9; + return true; + } + break; + case 'N': + case 'n': + switch (value) + { + case { } when value.Equals("NotFound", comparisonType): + result = -3; + return true; + } + break; + case 'S': + case 's': + switch (value) + { + case { } when value.Equals("Success", comparisonType): + result = 0; + return true; + case { } when value.Equals("ServerError", comparisonType): + result = -10; + return true; + } + break; + case 'T': + case 't': + switch (value) + { + case { } when value.Equals("Timeout", comparisonType): + result = -4; + return true; + } + break; + case 'U': + case 'u': + switch (value) + { + case { } when value.Equals("Unknown", comparisonType): + result = -1; + return true; + case { } when value.Equals("Unauthorized", comparisonType): + result = -5; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -193,15 +339,8 @@ public static bool TryParse( StringComparison comparisonType, out StatusCode result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (StatusCode)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -220,7 +359,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out StatusCode result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -235,7 +375,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static StatusCode? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out StatusCode result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (StatusCode?)result : null; } /// @@ -252,7 +392,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static StatusCode? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out StatusCode result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (StatusCode?)result : null; } /// @@ -265,9 +405,9 @@ public static bool TryParseIgnoreCase( /// is empty or does not represent a valid value. public static StatusCode ParseFromEnumMemberValue(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (StatusCode)result; } /// @@ -279,8 +419,8 @@ public static StatusCode ParseFromEnumMemberValue(string value, bool ignoreCase /// is empty or does not represent a valid value. public static StatusCode ParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (StatusCode)result; } /// @@ -294,8 +434,8 @@ public static StatusCode ParseFromEnumMemberValue(ReadOnlySpan value, bool public static StatusCode? ParseFromEnumMemberValueOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (StatusCode)result; } /// @@ -312,7 +452,8 @@ public static StatusCode ParseFromEnumMemberValue(ReadOnlySpan value, bool /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, bool ignoreCase, out StatusCode result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -328,7 +469,8 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, out StatusCode result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -342,7 +484,7 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// public static StatusCode? TryParseFromEnumMemberValue(string? value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out StatusCode result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (StatusCode?)result : null; } /// @@ -359,7 +501,8 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, out StatusCode result) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -375,7 +518,8 @@ public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ig /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out StatusCode result) { - return TryParseFromEnumMemberValue(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -389,25 +533,166 @@ public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out Sta /// public static StatusCode? TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out StatusCode result) ? result : null; + return TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (StatusCode?)result : null; } - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out StatusCode result) + private static bool TryParseEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) { - return TryParseFromEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure, out result); + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericEnumMemberValue(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericEnumMemberValue(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleEnumMemberValue(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out StatusCode result) + private static bool TryParseSingleEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, out int result) { - bool success = EnumStringParser.TryParse(value, s_serializationStringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (StatusCode)number; - return true; + switch (value[0]) + { + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("Conflict", comparisonType): + result = -7; + return true; + } + break; + case 'E': + case 'e': + switch (value) + { + case { } when value.Equals("Error", comparisonType): + result = -2; + return true; + } + break; + case 'F': + case 'f': + switch (value) + { + case { } when value.Equals("Forbidden", comparisonType): + result = -6; + return true; + } + break; + case 'G': + case 'g': + switch (value) + { + case { } when value.Equals("Gone", comparisonType): + result = -8; + return true; + } + break; + case 'I': + case 'i': + switch (value) + { + case { } when value.Equals("InvalidRequest", comparisonType): + result = -9; + return true; + } + break; + case 'N': + case 'n': + switch (value) + { + case { } when value.Equals("Not Found", comparisonType): + result = -3; + return true; + } + break; + case 'S': + case 's': + switch (value) + { + case { } when value.Equals("Success", comparisonType): + result = 0; + return true; + case { } when value.Equals("ServerError", comparisonType): + result = -10; + return true; + } + break; + case 'T': + case 't': + switch (value) + { + case { } when value.Equals("Timeout", comparisonType): + result = -4; + return true; + } + break; + case 'U': + case 'u': + switch (value) + { + case { } when value.Equals("Unknown", comparisonType): + result = -1; + return true; + case { } when value.Equals("Unauthorized", comparisonType): + result = -5; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -429,7 +714,8 @@ public static bool TryParseFromEnumMemberValue( StringComparison comparisonType, out StatusCode result) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -446,7 +732,7 @@ public static bool TryParseFromEnumMemberValue( [Obsolete("Use TryParseFromEnumMemberValue overload with 'ignoreCase' parameter")] public static StatusCode? TryParseFromEnumMemberValue(string? value, StringComparison comparisonType) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out StatusCode result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (StatusCode?)result : null; } public static bool TryCreateFromDisplayShortName( @@ -611,11 +897,5 @@ public static string[] GetNames() "ServerError", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeValidation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeValidation.g.cs index 3919622..a198e9c 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeValidation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.StatusCodeValidation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class StatusCodeValidation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleEnumInfo.g.cs index 1881502..4c89858 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleEnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleEnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class UserRoleMetadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 10; /// The string representation of name. @@ -42,7 +43,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 10; /// The UTF-8 representation of name. @@ -67,474 +68,51 @@ public static partial class Utf8Name /// Provides constant values for serialized members values. public static partial class SerializedValue { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by serializing a value to string, based on defined members. public const int MaxCharsLength = 11; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string None = "None"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string NormalUser = "Normal User"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Custodian = "Custodian"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string Finance = "Finance"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string SuperUser = "Super User"; - /// The string representation of serialized value. + /// The string representation of serialized value. public const string All = "All"; } - /// Provides static values for UTF-8 encoded members serialized values. + /// Provides static values for UTF-8 encoded serialized members values. public static partial class Utf8SerializedValue { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by serializing a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 11; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan None => new byte[4] { 78, 111, 110, 101 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan NormalUser => new byte[11] { 78, 111, 114, 109, 97, 108, 32, 85, 115, 101, 114 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Custodian => new byte[9] { 67, 117, 115, 116, 111, 100, 105, 97, 110 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan Finance => new byte[7] { 70, 105, 110, 97, 110, 99, 101 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan SuperUser => new byte[10] { 83, 117, 112, 101, 114, 32, 85, 115, 101, 114 }; - /// The UTF-8 representation of serialized value. + /// The UTF-8 representation of serialized value. public static ReadOnlySpan All => new byte[3] { 65, 108, 108 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFlagsFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(ulong value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(ulong value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(ulong value) - { - if (value == 0) - { - return 4; - } - - int count = 0, foundItemsCount = 0; - if ((value & 7) == 7) - { - value -= 7; - count = checked(count + 3); - foundItemsCount++; - } - if ((value & 6) == 6) - { - value -= 6; - count = checked(count + 9); - foundItemsCount++; - } - if ((value & 4) == 4) - { - value -= 4; - count = checked(count + 7); - foundItemsCount++; - } - if ((value & 2) == 2) - { - value -= 2; - count = checked(count + 9); - foundItemsCount++; - } - if ((value & 1) == 1) - { - value -= 1; - count = checked(count + 10); - foundItemsCount++; - } - - if (value != 0) - { - return null; - } - - const int separatorStringLength = 2; - return checked(count + (separatorStringLength * (foundItemsCount - 1))); - } - - /// - public string? TryGetStringForMember(ulong value) - { - if (value == 0) - { - return "None"; - } - - Span foundItems = stackalloc ulong[3]; - int count = 0, foundItemsCount = 0; - if ((value & 7) == 7) - { - value -= 7; - count = checked(count + 3); - foundItems[foundItemsCount++] = 7; - } - if ((value & 6) == 6) - { - value -= 6; - count = checked(count + 9); - foundItems[foundItemsCount++] = 6; - } - if ((value & 4) == 4) - { - value -= 4; - count = checked(count + 7); - foundItems[foundItemsCount++] = 4; - } - if ((value & 2) == 2) - { - value -= 2; - count = checked(count + 9); - foundItems[foundItemsCount++] = 2; - } - if ((value & 1) == 1) - { - value -= 1; - count = checked(count + 10); - foundItems[foundItemsCount++] = 1; - } - - if (value != 0) - { - return null; - } - - if (foundItemsCount == 1) - { - return GetStringForSingleMember(foundItems[0]); - } - - return EnumStringFormatter.WriteMultipleFoundFlagsNames(this, count, foundItemsCount, foundItems); - } - - public string GetStringForSingleMember(ulong value) - { - return value switch - { - 0 => "None", - 1 => "NormalUser", - 2 => "Custodian", - 4 => "Finance", - 6 => "SuperUser", - 7 => "All", - _ => throw new ArgumentOutOfRangeException() - }; - } - } - - /// Provides support for formatting serialized values. - internal sealed partial class SerializationStringFormatter : IEnumFlagsFormatter - { - /// Gets the singleton instance of the class. - public static SerializationStringFormatter Instance = new SerializationStringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(ulong value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(ulong value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(ulong value) - { - if (value == 0) - { - return 4; - } - - int count = 0, foundItemsCount = 0; - if ((value & 7) == 7) - { - value -= 7; - count = checked(count + 3); - foundItemsCount++; - } - if ((value & 6) == 6) - { - value -= 6; - count = checked(count + 10); - foundItemsCount++; - } - if ((value & 4) == 4) - { - value -= 4; - count = checked(count + 7); - foundItemsCount++; - } - if ((value & 2) == 2) - { - value -= 2; - count = checked(count + 9); - foundItemsCount++; - } - if ((value & 1) == 1) - { - value -= 1; - count = checked(count + 11); - foundItemsCount++; - } - - if (value != 0) - { - return null; - } - - const int separatorStringLength = 2; - return checked(count + (separatorStringLength * (foundItemsCount - 1))); - } - - /// - public string? TryGetStringForMember(ulong value) - { - if (value == 0) - { - return "None"; - } - - Span foundItems = stackalloc ulong[3]; - int count = 0, foundItemsCount = 0; - if ((value & 7) == 7) - { - value -= 7; - count = checked(count + 3); - foundItems[foundItemsCount++] = 7; - } - if ((value & 6) == 6) - { - value -= 6; - count = checked(count + 10); - foundItems[foundItemsCount++] = 6; - } - if ((value & 4) == 4) - { - value -= 4; - count = checked(count + 7); - foundItems[foundItemsCount++] = 4; - } - if ((value & 2) == 2) - { - value -= 2; - count = checked(count + 9); - foundItems[foundItemsCount++] = 2; - } - if ((value & 1) == 1) - { - value -= 1; - count = checked(count + 11); - foundItems[foundItemsCount++] = 1; - } - - if (value != 0) - { - return null; - } - - if (foundItemsCount == 1) - { - return GetStringForSingleMember(foundItems[0]); - } - - return EnumStringFormatter.WriteMultipleFoundFlagsNames(this, count, foundItemsCount, foundItems); - } - - public string GetStringForSingleMember(ulong value) - { - return value switch - { - 0 => "None", - 1 => "Normal User", - 2 => "Custodian", - 4 => "Finance", - 6 => "Super User", - 7 => "All", - _ => throw new ArgumentOutOfRangeException() - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ulong BitwiseOr(ulong value1, ulong value2) => unchecked((ulong)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out ulong result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out ulong result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'N': - case 'n': - switch (value) - { - case { } when value.Equals("None", comparisonType): - result = 0; - return true; - case { } when value.Equals("NormalUser", comparisonType): - result = 1; - return true; - } - goto default; - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("Custodian", comparisonType): - result = 2; - return true; - } - goto default; - case 'F': - case 'f': - switch (value) - { - case { } when value.Equals("Finance", comparisonType): - result = 4; - return true; - } - goto default; - case 'S': - case 's': - switch (value) - { - case { } when value.Equals("SuperUser", comparisonType): - result = 6; - return true; - } - goto default; - case 'A': - case 'a': - switch (value) - { - case { } when value.Equals("All", comparisonType): - result = 7; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } - - /// Provides support for parsing serialized values. - internal sealed partial class SerializationStringParser : IEnumParser - { - /// Gets the singleton instance of the class. - public static SerializationStringParser Instance = new SerializationStringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ulong BitwiseOr(ulong value1, ulong value2) => unchecked((ulong)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out ulong result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out ulong result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'N': - case 'n': - switch (value) - { - case { } when value.Equals("None", comparisonType): - result = 0; - return true; - case { } when value.Equals("Normal User", comparisonType): - result = 1; - return true; - } - goto default; - case 'C': - case 'c': - switch (value) - { - case { } when value.Equals("Custodian", comparisonType): - result = 2; - return true; - } - goto default; - case 'F': - case 'f': - switch (value) - { - case { } when value.Equals("Finance", comparisonType): - result = 4; - return true; - } - goto default; - case 'S': - case 's': - switch (value) - { - case { } when value.Equals("Super User", comparisonType): - result = 6; - return true; - } - goto default; - case 'A': - case 'a': - switch (value) - { - case { } when value.Equals("All", comparisonType): - result = 7; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleExtensions.g.cs index eabefb6..f4421d7 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleExtensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleExtensions.g.cs @@ -11,22 +11,21 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class UserRoleExtensions { - private static readonly UserRoleMetadata.StringFormatter s_stringFormatter = UserRoleMetadata.StringFormatter.Instance; - private static readonly UserRoleMetadata.SerializationStringFormatter s_serializationStringFormatter = UserRoleMetadata.SerializationStringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this UserRole value) { - return EnumStringFormatter.GetString((ulong)value, s_stringFormatter); + return FormatFlagNames((ulong)value) + ?? ((ulong)value).ToString(); } /// Determines whether one or more bit fields are set in the current instance. /// An enumeration value. /// if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, . + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasFlagFast(this UserRole value, UserRole flag) { return (value & flag) == flag; @@ -37,14 +36,178 @@ public static bool HasFlagFast(this UserRole value, UserRole flag) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this UserRole value) { - return EnumStringFormatter.GetStringLength((ulong)value, s_stringFormatter); + return FormatFlagNamesLength((ulong)value) + ?? EnumNumericFormatter.GetStringLength((ulong)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this UserRole value) { - return UserRoleValidation.IsDefined(value); + return (ulong)value switch + { + 0 => true, + 1 => true, + 2 => true, + 4 => true, + 6 => true, + 7 => true, + _ => false + }; + } + + private static int? FormatFlagNamesLength(ulong value) + { + int? fastResult = GetNameLengthInlined(value); + if (fastResult is not null) + { + return fastResult.Value; + } + + if (value == 0) + { + return 1; + } + + int count = 0, foundItemsCount = 0; + if (true) + { + if ((value & 7) == 7) + { + value -= 7; + count = checked(count + 3); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 6) == 6) + { + value -= 6; + count = checked(count + 9); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 4) == 4) + { + value -= 4; + count = checked(count + 7); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 2) == 2) + { + value -= 2; + count = checked(count + 9); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 1) == 1) + { + value -= 1; + count = checked(count + 10); + foundItemsCount++; + if (value == 0) goto CountLength; + } + } + + if (value != 0) + { + return null; + } + + CountLength: + const int separatorStringLength = 2; + return checked(count + (separatorStringLength * (foundItemsCount - 1))); + } + + private static readonly string[] s_formatNames = new string[6] { "All", "SuperUser", "Finance", "Custodian", "NormalUser", "None" }; + + private static string? FormatFlagNames(ulong value) + { + string? result = GetNameInlined(value); + if (result is null) + { + Span foundItems = stackalloc int[3]; + if (TryFindFlagsNames(value, foundItems, out int foundItemsCount, out int resultLength)) + { + result = EnumStringFormatter.WriteMultipleFoundFlagsNames(s_formatNames, foundItems, foundItemsCount, resultLength); + } + } + + return result; + } + + private static bool TryFindFlagsNames(ulong value, Span foundItems, out int foundItemsCount, out int resultLength) + { + resultLength = 0; + foundItemsCount = 0; + if (true) + { + if ((value & 7) == 7) + { + value -= 7; + resultLength = checked(resultLength + 3); + foundItems[foundItemsCount++] = 0; + if (value == 0) return true; + } + if ((value & 6) == 6) + { + value -= 6; + resultLength = checked(resultLength + 9); + foundItems[foundItemsCount++] = 1; + if (value == 0) return true; + } + if ((value & 4) == 4) + { + value -= 4; + resultLength = checked(resultLength + 7); + foundItems[foundItemsCount++] = 2; + if (value == 0) return true; + } + if ((value & 2) == 2) + { + value -= 2; + resultLength = checked(resultLength + 9); + foundItems[foundItemsCount++] = 3; + if (value == 0) return true; + } + if ((value & 1) == 1) + { + value -= 1; + resultLength = checked(resultLength + 10); + foundItems[foundItemsCount++] = 4; + if (value == 0) return true; + } + } + + return value == 0; + } + + private static int? GetNameLengthInlined(ulong value) + { + return value switch + { + 0 => 4, + 1 => 10, + 2 => 9, + 4 => 7, + 6 => 9, + 7 => 3, + _ => null + }; + } + + private static string? GetNameInlined(ulong value) + { + return value switch + { + 0 => "None", + 1 => "NormalUser", + 2 => "Custodian", + 4 => "Finance", + 6 => "SuperUser", + 7 => "All", + _ => null + }; } #if NET5_0_OR_GREATER @@ -106,12 +269,168 @@ public static UserRole InterlockedRead(this ref UserRole location) public static string ToEnumMemberValue(this UserRole value) { - return EnumStringFormatter.GetString((ulong)value, s_serializationStringFormatter); + return FormatFlagEnumMemberValues((ulong)value) + ?? ((ulong)value).ToString(); } public static int GetEnumMemberValueStringLength(this UserRole value) { - return EnumStringFormatter.GetStringLength((ulong)value, s_serializationStringFormatter); + return FormatFlagEnumMemberValuesLength((ulong)value) + ?? EnumNumericFormatter.GetStringLength((ulong)value); + } + + private static int? FormatFlagEnumMemberValuesLength(ulong value) + { + int? fastResult = GetEnumMemberValueLengthInlined(value); + if (fastResult is not null) + { + return fastResult.Value; + } + + if (value == 0) + { + return 1; + } + + int count = 0, foundItemsCount = 0; + if (true) + { + if ((value & 7) == 7) + { + value -= 7; + count = checked(count + 3); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 6) == 6) + { + value -= 6; + count = checked(count + 10); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 4) == 4) + { + value -= 4; + count = checked(count + 7); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 2) == 2) + { + value -= 2; + count = checked(count + 9); + foundItemsCount++; + if (value == 0) goto CountLength; + } + if ((value & 1) == 1) + { + value -= 1; + count = checked(count + 11); + foundItemsCount++; + if (value == 0) goto CountLength; + } + } + + if (value != 0) + { + return null; + } + + CountLength: + const int separatorStringLength = 2; + return checked(count + (separatorStringLength * (foundItemsCount - 1))); + } + + private static readonly string[] s_formatEnumMemberValues = new string[6] { "All", "Super User", "Finance", "Custodian", "Normal User", "None" }; + + private static string? FormatFlagEnumMemberValues(ulong value) + { + string? result = GetEnumMemberValueInlined(value); + if (result is null) + { + Span foundItems = stackalloc int[3]; + if (TryFindFlagsEnumMemberValues(value, foundItems, out int foundItemsCount, out int resultLength)) + { + result = EnumStringFormatter.WriteMultipleFoundFlagsNames(s_formatEnumMemberValues, foundItems, foundItemsCount, resultLength); + } + } + + return result; + } + + private static bool TryFindFlagsEnumMemberValues(ulong value, Span foundItems, out int foundItemsCount, out int resultLength) + { + resultLength = 0; + foundItemsCount = 0; + if (true) + { + if ((value & 7) == 7) + { + value -= 7; + resultLength = checked(resultLength + 3); + foundItems[foundItemsCount++] = 0; + if (value == 0) return true; + } + if ((value & 6) == 6) + { + value -= 6; + resultLength = checked(resultLength + 10); + foundItems[foundItemsCount++] = 1; + if (value == 0) return true; + } + if ((value & 4) == 4) + { + value -= 4; + resultLength = checked(resultLength + 7); + foundItems[foundItemsCount++] = 2; + if (value == 0) return true; + } + if ((value & 2) == 2) + { + value -= 2; + resultLength = checked(resultLength + 9); + foundItems[foundItemsCount++] = 3; + if (value == 0) return true; + } + if ((value & 1) == 1) + { + value -= 1; + resultLength = checked(resultLength + 11); + foundItems[foundItemsCount++] = 4; + if (value == 0) return true; + } + } + + return value == 0; + } + + private static int? GetEnumMemberValueLengthInlined(ulong value) + { + return value switch + { + 0 => 4, + 1 => 11, + 2 => 9, + 4 => 7, + 6 => 10, + 7 => 3, + _ => null + }; + } + + private static string? GetEnumMemberValueInlined(ulong value) + { + return value switch + { + 0 => "None", + 1 => "Normal User", + 2 => "Custodian", + 4 => "Finance", + 6 => "Super User", + 7 => "All", + _ => null + }; } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleFactory.g.cs index e1c0e72..9212081 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleFactory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleFactory.g.cs @@ -12,12 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class UserRoleFactory { - private static readonly UserRoleMetadata.StringParser s_stringParser = UserRoleMetadata.StringParser.Instance; - private static readonly UserRoleMetadata.SerializationStringParser s_serializationStringParser = UserRoleMetadata.SerializationStringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -29,9 +26,9 @@ public static partial class UserRoleFactory /// is empty or does not represent a valid value. public static UserRole Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (UserRole)result; } /// @@ -44,8 +41,8 @@ public static UserRole Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static UserRole Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (UserRole)result; } /// @@ -60,8 +57,8 @@ public static UserRole Parse(ReadOnlySpan value, bool ignoreCase = false) public static UserRole? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (UserRole)result; } /// @@ -78,7 +75,8 @@ public static UserRole Parse(ReadOnlySpan value, bool ignoreCase = false) /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out UserRole result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -94,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out UserRole result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -109,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out UserRole resu /// public static UserRole? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out UserRole result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (UserRole?)result : null; } /// @@ -126,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out UserRole resu /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out UserRole result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -142,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out UserR /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out UserRole result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -157,21 +158,142 @@ public static bool TryParse(ReadOnlySpan value, out UserRole result) /// public static UserRole? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out UserRole result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (UserRole?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out ulong result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out UserRole result) + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out ulong result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out ulong number); - if (!success) + bool parsed = true; + ulong localResult = 0; + foreach (var item in new FlagsEnumTokenizer(value)) + { + bool success = TryParseSingleName(item, comparisonType, out ulong singleValue); + if (!success) + { + parsed = false; + break; + } + + localResult |= singleValue; + } + + if (parsed) + { + result = localResult; + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out ulong result) + { + if (value.IsEmpty) { result = 0; return false; } - result = (UserRole)number; - return true; + switch (value[0]) + { + case 'A': + case 'a': + switch (value) + { + case { } when value.Equals("All", comparisonType): + result = 7; + return true; + } + break; + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("Custodian", comparisonType): + result = 2; + return true; + } + break; + case 'F': + case 'f': + switch (value) + { + case { } when value.Equals("Finance", comparisonType): + result = 4; + return true; + } + break; + case 'N': + case 'n': + switch (value) + { + case { } when value.Equals("None", comparisonType): + result = 0; + return true; + case { } when value.Equals("NormalUser", comparisonType): + result = 1; + return true; + } + break; + case 'S': + case 's': + switch (value) + { + case { } when value.Equals("SuperUser", comparisonType): + result = 6; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -193,15 +315,8 @@ public static bool TryParse( StringComparison comparisonType, out UserRole result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out ulong number); - if (!success) - { - result = 0; - return false; - } - - result = (UserRole)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -220,7 +335,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out UserRole result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -235,7 +351,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static UserRole? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out UserRole result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (UserRole?)result : null; } /// @@ -252,7 +368,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static UserRole? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out UserRole result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (UserRole?)result : null; } /// @@ -265,9 +381,9 @@ public static bool TryParseIgnoreCase( /// is empty or does not represent a valid value. public static UserRole ParseFromEnumMemberValue(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (UserRole)result; } /// @@ -279,8 +395,8 @@ public static UserRole ParseFromEnumMemberValue(string value, bool ignoreCase = /// is empty or does not represent a valid value. public static UserRole ParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (UserRole)result; } /// @@ -294,8 +410,8 @@ public static UserRole ParseFromEnumMemberValue(ReadOnlySpan value, bool i public static UserRole? ParseFromEnumMemberValueOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (UserRole)result; } /// @@ -312,7 +428,8 @@ public static UserRole ParseFromEnumMemberValue(ReadOnlySpan value, bool i /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, bool ignoreCase, out UserRole result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -328,7 +445,8 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value, out UserRole result) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -342,7 +460,7 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// public static UserRole? TryParseFromEnumMemberValue(string? value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value.AsSpan(), ignoreCase, throwOnFailure: false, out UserRole result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (UserRole?)result : null; } /// @@ -359,7 +477,8 @@ public static bool TryParseFromEnumMemberValue([NotNullWhen(true)] string? value /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, out UserRole result) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -375,7 +494,8 @@ public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ig /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out UserRole result) { - return TryParseFromEnumMemberValue(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -389,25 +509,142 @@ public static bool TryParseFromEnumMemberValue(ReadOnlySpan value, out Use /// public static UserRole? TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase = false) { - return TryParseFromEnumMemberValue(value, ignoreCase, throwOnFailure: false, out UserRole result) ? result : null; + return TryParseEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (UserRole?)result : null; } - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out UserRole result) + private static bool TryParseEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out ulong result) { - return TryParseFromEnumMemberValue(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure, out result); + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericEnumMemberValue(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericEnumMemberValue(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; } - private static bool TryParseFromEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out UserRole result) + private static bool TryParseNonNumericEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out ulong result) { - bool success = EnumStringParser.TryParse(value, s_serializationStringParser, comparisonType, throwOnFailure, out ulong number); - if (!success) + bool parsed = true; + ulong localResult = 0; + foreach (var item in new FlagsEnumTokenizer(value)) + { + bool success = TryParseSingleEnumMemberValue(item, comparisonType, out ulong singleValue); + if (!success) + { + parsed = false; + break; + } + + localResult |= singleValue; + } + + if (parsed) + { + result = localResult; + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseSingleEnumMemberValue(ReadOnlySpan value, StringComparison comparisonType, out ulong result) + { + if (value.IsEmpty) { result = 0; return false; } - result = (UserRole)number; - return true; + switch (value[0]) + { + case 'A': + case 'a': + switch (value) + { + case { } when value.Equals("All", comparisonType): + result = 7; + return true; + } + break; + case 'C': + case 'c': + switch (value) + { + case { } when value.Equals("Custodian", comparisonType): + result = 2; + return true; + } + break; + case 'F': + case 'f': + switch (value) + { + case { } when value.Equals("Finance", comparisonType): + result = 4; + return true; + } + break; + case 'N': + case 'n': + switch (value) + { + case { } when value.Equals("None", comparisonType): + result = 0; + return true; + case { } when value.Equals("Normal User", comparisonType): + result = 1; + return true; + } + break; + case 'S': + case 's': + switch (value) + { + case { } when value.Equals("Super User", comparisonType): + result = 6; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -429,7 +666,8 @@ public static bool TryParseFromEnumMemberValue( StringComparison comparisonType, out UserRole result) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -446,7 +684,7 @@ public static bool TryParseFromEnumMemberValue( [Obsolete("Use TryParseFromEnumMemberValue overload with 'ignoreCase' parameter")] public static UserRole? TryParseFromEnumMemberValue(string? value, StringComparison comparisonType) { - return TryParseFromEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out UserRole result) ? result : null; + return TryParseEnumMemberValue(value.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (UserRole?)result : null; } /// Retrieves an array of the values of the constants in the UserRole enumeration. @@ -478,11 +716,5 @@ public static string[] GetNames() "All", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleValidation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleValidation.g.cs index 2dc98e3..a4ede31 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleValidation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.UserRoleValidation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class UserRoleValidation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysEnumInfo.g.cs index b5bc5b2..fe60049 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysEnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysEnumInfo.g.cs @@ -10,14 +10,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { + /// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class WeekDaysMetadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 9; /// The string representation of name. @@ -45,7 +46,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 9; /// The UTF-8 representation of name. @@ -69,135 +70,5 @@ public static partial class Utf8Name /// The UTF-8 representation of name. public static ReadOnlySpan Sunday => new byte[6] { 83, 117, 110, 100, 97, 121 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 0 => 6, - 1 => 7, - 2 => 9, - 3 => 8, - 4 => 6, - 5 => 8, - 6 => 6, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 0 => "Monday", - 1 => "Tuesday", - 2 => "Wednesday", - 3 => "Thursday", - 4 => "Friday", - 5 => "Saturday", - 6 => "Sunday", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'M': - case 'm': - switch (value) - { - case { } when value.Equals("Monday", comparisonType): - result = 0; - return true; - } - goto default; - case 'T': - case 't': - switch (value) - { - case { } when value.Equals("Tuesday", comparisonType): - result = 1; - return true; - case { } when value.Equals("Thursday", comparisonType): - result = 3; - return true; - } - goto default; - case 'W': - case 'w': - switch (value) - { - case { } when value.Equals("Wednesday", comparisonType): - result = 2; - return true; - } - goto default; - case 'F': - case 'f': - switch (value) - { - case { } when value.Equals("Friday", comparisonType): - result = 4; - return true; - } - goto default; - case 'S': - case 's': - switch (value) - { - case { } when value.Equals("Saturday", comparisonType): - result = 5; - return true; - case { } when value.Equals("Sunday", comparisonType): - result = 6; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysExtensions.g.cs index af27377..cdc218d 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysExtensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysExtensions.g.cs @@ -11,16 +11,15 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class WeekDaysExtensions { - private static readonly WeekDaysMetadata.StringFormatter s_stringFormatter = WeekDaysMetadata.StringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this WeekDays value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return GetNameInlined((int)value) + ?? ((int)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -28,14 +27,55 @@ public static string ToStringFast(this WeekDays value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this WeekDays value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return GetNameLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this WeekDays value) { - return WeekDaysValidation.IsDefined(value); + return (int)value switch + { + 0 => true, + 1 => true, + 2 => true, + 3 => true, + 4 => true, + 5 => true, + 6 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + 0 => 6, + 1 => 7, + 2 => 9, + 3 => 8, + 4 => 6, + 5 => 8, + 6 => 6, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + 0 => "Monday", + 1 => "Tuesday", + 2 => "Wednesday", + 3 => "Thursday", + 4 => "Friday", + 5 => "Saturday", + 6 => "Sunday", + _ => null + }; } /// Adds two enumerations and replaces the first integer with the sum, as an atomic operation. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysFactory.g.cs index f798476..9479006 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysFactory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysFactory.g.cs @@ -12,11 +12,9 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class WeekDaysFactory { - private static readonly WeekDaysMetadata.StringParser s_stringParser = WeekDaysMetadata.StringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -28,9 +26,9 @@ public static partial class WeekDaysFactory /// is empty or does not represent a valid value. public static WeekDays Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (WeekDays)result; } /// @@ -43,8 +41,8 @@ public static WeekDays Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static WeekDays Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (WeekDays)result; } /// @@ -59,8 +57,8 @@ public static WeekDays Parse(ReadOnlySpan value, bool ignoreCase = false) public static WeekDays? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (WeekDays)result; } /// @@ -77,7 +75,8 @@ public static WeekDays Parse(ReadOnlySpan value, bool ignoreCase = false) /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out WeekDays result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -93,7 +92,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out WeekDays result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -108,7 +108,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out WeekDays resu /// public static WeekDays? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out WeekDays result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (WeekDays?)result : null; } /// @@ -125,7 +125,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out WeekDays resu /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out WeekDays result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -141,7 +142,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out WeekD /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out WeekDays result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -156,21 +158,130 @@ public static bool TryParse(ReadOnlySpan value, out WeekDays result) /// public static WeekDays? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out WeekDays result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (WeekDays?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out WeekDays result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (WeekDays)number; - return true; + switch (value[0]) + { + case 'F': + case 'f': + switch (value) + { + case { } when value.Equals("Friday", comparisonType): + result = 4; + return true; + } + break; + case 'M': + case 'm': + switch (value) + { + case { } when value.Equals("Monday", comparisonType): + result = 0; + return true; + } + break; + case 'S': + case 's': + switch (value) + { + case { } when value.Equals("Saturday", comparisonType): + result = 5; + return true; + case { } when value.Equals("Sunday", comparisonType): + result = 6; + return true; + } + break; + case 'T': + case 't': + switch (value) + { + case { } when value.Equals("Tuesday", comparisonType): + result = 1; + return true; + case { } when value.Equals("Thursday", comparisonType): + result = 3; + return true; + } + break; + case 'W': + case 'w': + switch (value) + { + case { } when value.Equals("Wednesday", comparisonType): + result = 2; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -192,15 +303,8 @@ public static bool TryParse( StringComparison comparisonType, out WeekDays result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (WeekDays)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -219,7 +323,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out WeekDays result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -234,7 +339,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static WeekDays? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out WeekDays result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (WeekDays?)result : null; } /// @@ -251,7 +356,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static WeekDays? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out WeekDays result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (WeekDays?)result : null; } public static bool TryCreateFromDisplayShortName( @@ -422,11 +527,5 @@ public static string[] GetNames() "Sunday", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysValidation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysValidation.g.cs index 2363885..e098ae8 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysValidation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/Raiqub.Generators.EnumUtilities.IntegrationTests.Models.WeekDaysValidation.g.cs @@ -9,7 +9,7 @@ namespace Raiqub.Generators.EnumUtilities.IntegrationTests.Models { [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class WeekDaysValidation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceEnumInfo.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceEnumInfo.g.cs index 100f672..8fb5973 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceEnumInfo.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceEnumInfo.g.cs @@ -8,14 +8,15 @@ #pragma warning disable CS1591 // publicly visible type or member must be documented +/// Provides metadata for enumeration. [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class NoNamespaceMetadata { /// Provides constant values for members names. public static partial class Name { - /// Represents the largest possible number of characters produced by converting an value to string, based on defined members. This field is constant. + /// Represents the largest possible number of characters produced by converting a value to string, based on defined members. public const int MaxCharsLength = 4; /// The string representation of name. @@ -31,7 +32,7 @@ public static partial class Name /// Provides static values for UTF-8 encoded members names. public static partial class Utf8Name { - /// Represents the largest possible number of bytes produced by converting an value to UTF-8 string, based on defined members. This field is constant. + /// Represents the largest possible number of bytes produced by converting a value to UTF-8 string, based on defined members. public const int MaxBytesLength = 4; /// The UTF-8 representation of name. @@ -43,102 +44,4 @@ public static partial class Utf8Name /// The UTF-8 representation of name. public static ReadOnlySpan Two => new byte[3] { 84, 119, 111 }; } - - /// Provides support for formatting values. - internal sealed partial class StringFormatter : IEnumFormatter - { - /// Gets the singleton instance of the class. - public static StringFormatter Instance = new StringFormatter(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetStringLengthForNumber(int value) => EnumNumericFormatter.GetStringLength(value); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string GetStringForNumber(int value) => value.ToString(); - - /// - public int? TryGetStringLengthForMember(int value) - { - return value switch - { - 0 => 4, - 1 => 3, - 2 => 3, - _ => null - }; - } - - /// - public string? TryGetStringForMember(int value) - { - return value switch - { - 0 => "Zero", - 1 => "One", - 2 => "Two", - _ => null - }; - } - } - - /// Provides support for parsing values. - internal sealed partial class StringParser - : IEnumParser - { - /// Gets the singleton instance of the class. - public static StringParser Instance = new StringParser(); - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int BitwiseOr(int value1, int value2) => unchecked((int)(value1 | value2)); - - /// - public bool TryParseNumber(ReadOnlySpan value, out int result) => EnumNumericParser.TryParse(value, out result); - - /// - public bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) - { - if (value.IsEmpty) - { - result = 0; - return false; - } - - switch (value[0]) - { - case 'Z': - case 'z': - switch (value) - { - case { } when value.Equals("Zero", comparisonType): - result = 0; - return true; - } - goto default; - case 'O': - case 'o': - switch (value) - { - case { } when value.Equals("One", comparisonType): - result = 1; - return true; - } - goto default; - case 'T': - case 't': - switch (value) - { - case { } when value.Equals("Two", comparisonType): - result = 2; - return true; - } - goto default; - default: - result = 0; - return false; - } - } - } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceExtensions.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceExtensions.g.cs index a47ec46..f273fc2 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceExtensions.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceExtensions.g.cs @@ -9,16 +9,15 @@ #pragma warning disable CS1591 // publicly visible type or member must be documented [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class NoNamespaceExtensions { - private static readonly NoNamespaceMetadata.StringFormatter s_stringFormatter = NoNamespaceMetadata.StringFormatter.Instance; - /// Converts the value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public static string ToStringFast(this NoNamespace value) { - return EnumStringFormatter.GetString((int)value, s_stringFormatter); + return GetNameInlined((int)value) + ?? ((int)value).ToString(); } /// Calculates the number of characters produced by converting the specified value to string. @@ -26,14 +25,43 @@ public static string ToStringFast(this NoNamespace value) /// The number of characters produced by converting the specified value to string. public static int GetStringLength(this NoNamespace value) { - return EnumStringFormatter.GetStringLength((int)value, s_stringFormatter); + return GetNameLengthInlined((int)value) + ?? EnumNumericFormatter.GetStringLength((int)value); } /// Returns a boolean telling whether the value of this instance exists in the enumeration. /// true if the value of this instance exists in the enumeration; false otherwise. public static bool IsDefined(this NoNamespace value) { - return NoNamespaceValidation.IsDefined(value); + return (int)value switch + { + 0 => true, + 1 => true, + 2 => true, + _ => false + }; + } + + private static int? GetNameLengthInlined(int value) + { + return value switch + { + 0 => 4, + 1 => 3, + 2 => 3, + _ => null + }; + } + + private static string? GetNameInlined(int value) + { + return value switch + { + 0 => "Zero", + 1 => "One", + 2 => "Two", + _ => null + }; } /// Adds two enumerations and replaces the first integer with the sum, as an atomic operation. diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceFactory.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceFactory.g.cs index 319922a..f5cd3d6 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceFactory.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceFactory.g.cs @@ -10,11 +10,9 @@ #pragma warning disable CS1591 // publicly visible type or member must be documented [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class NoNamespaceFactory { - private static readonly NoNamespaceMetadata.StringParser s_stringParser = NoNamespaceMetadata.StringParser.Instance; - /// /// Converts the string representation of the name or numeric value of one or more enumerated constants to /// an equivalent enumerated object. @@ -26,9 +24,9 @@ public static partial class NoNamespaceFactory /// is empty or does not represent a valid value. public static NoNamespace Parse(string value, bool ignoreCase = false) { - if (value is null) ThrowArgumentNullException(nameof(value)); - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + if (value is null) ThrowHelper.ThrowArgumentNullException(nameof(value)); + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NoNamespace)result; } /// @@ -41,8 +39,8 @@ public static NoNamespace Parse(string value, bool ignoreCase = false) /// is empty or does not represent a valid value. public static NoNamespace Parse(ReadOnlySpan value, bool ignoreCase = false) { - TryParse(value, ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NoNamespace)result; } /// @@ -57,8 +55,8 @@ public static NoNamespace Parse(ReadOnlySpan value, bool ignoreCase = fals public static NoNamespace? ParseOrNull(string? value, bool ignoreCase = false) { if (value is null) return null; - TryParse(value.AsSpan(), ignoreCase, throwOnFailure: true, out var result); - return result; + TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: true, out var result); + return (NoNamespace)result; } /// @@ -75,7 +73,8 @@ public static NoNamespace Parse(ReadOnlySpan value, bool ignoreCase = fals /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, out NoNamespace result) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -91,7 +90,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, bool ignoreCase, /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse([NotNullWhen(true)] string? value, out NoNamespace result) { - return TryParse(value.AsSpan(), ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value.AsSpan(), StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -106,7 +106,7 @@ public static bool TryParse([NotNullWhen(true)] string? value, out NoNamespace r /// public static NoNamespace? TryParse(string? value, bool ignoreCase = false) { - return TryParse(value.AsSpan(), ignoreCase, throwOnFailure: false, out NoNamespace result) ? result : null; + return TryParseName(value.AsSpan(), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NoNamespace?)result : null; } /// @@ -123,7 +123,8 @@ public static bool TryParse([NotNullWhen(true)] string? value, out NoNamespace r /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out NoNamespace result) { - return TryParse(value, ignoreCase, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -139,7 +140,8 @@ public static bool TryParse(ReadOnlySpan value, bool ignoreCase, out NoNam /// true if the value parameter was converted successfully; otherwise, false. public static bool TryParse(ReadOnlySpan value, out NoNamespace result) { - return TryParse(value, ignoreCase: false, throwOnFailure: false, out result); + Unsafe.SkipInit(out result); + return TryParseName(value, StringComparison.Ordinal, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -154,21 +156,106 @@ public static bool TryParse(ReadOnlySpan value, out NoNamespace result) /// public static NoNamespace? TryParse(ReadOnlySpan value, bool ignoreCase = false) { - return TryParse(value, ignoreCase, throwOnFailure: false, out NoNamespace result) ? result : null; + return TryParseName(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal, throwOnFailure: false, out var result) ? (NoNamespace?)result : null; + } + + private static bool TryParseName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) + { + goto ParseFailure; + } + + c = value[0]; + } + + if ((c < '0' || c > '9') && c != '-' && c != '+') + { + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + bool success = EnumNumericParser.TryParse(value, out result); + if (success) + { + return true; + } + + return TryParseNonNumericName(value, comparisonType, throwOnFailure, out result); + } + + ParseFailure: + if (throwOnFailure) + { + ThrowHelper.ThrowInvalidEmptyParseArgument(nameof(value)); + } + + result = 0; + return false; + } + + private static bool TryParseNonNumericName(ReadOnlySpan value, StringComparison comparisonType, bool throwOnFailure, out int result) + { + bool success = TryParseSingleName(value, comparisonType, out result); + if (success) + { + return true; + } + + if (throwOnFailure) + { + ThrowHelper.ThrowValueNotFound(value, nameof(value)); + } + + return false; } - private static bool TryParse(ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out NoNamespace result) + private static bool TryParseSingleName(ReadOnlySpan value, StringComparison comparisonType, out int result) { - var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - bool success = EnumStringParser.TryParse(value, s_stringParser, comparisonType, throwOnFailure, out int number); - if (!success) + if (value.IsEmpty) { result = 0; return false; } - result = (NoNamespace)number; - return true; + switch (value[0]) + { + case 'O': + case 'o': + switch (value) + { + case { } when value.Equals("One", comparisonType): + result = 1; + return true; + } + break; + case 'T': + case 't': + switch (value) + { + case { } when value.Equals("Two", comparisonType): + result = 2; + return true; + } + break; + case 'Z': + case 'z': + switch (value) + { + case { } when value.Equals("Zero", comparisonType): + result = 0; + return true; + } + break; + } + + result = 0; + return false; } /// @@ -190,15 +277,8 @@ public static bool TryParse( StringComparison comparisonType, out NoNamespace result) { - bool success = EnumStringParser.TryParse(name, s_stringParser, comparisonType, throwOnFailure: false, out int number); - if (!success) - { - result = 0; - return false; - } - - result = (NoNamespace)number; - return true; + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -217,7 +297,8 @@ public static bool TryParseIgnoreCase( [NotNullWhen(true)] string? name, out NoNamespace result) { - return TryParse(name.AsSpan(), ignoreCase: true, out result); + Unsafe.SkipInit(out result); + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out Unsafe.As(ref result)); } /// @@ -232,7 +313,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static NoNamespace? TryParseIgnoreCase(string? name) { - return TryParse(name.AsSpan(), ignoreCase: true, out NoNamespace result) ? result : null; + return TryParseName(name.AsSpan(), StringComparison.OrdinalIgnoreCase, throwOnFailure: false, out var result) ? (NoNamespace?)result : null; } /// @@ -249,7 +330,7 @@ public static bool TryParseIgnoreCase( [Obsolete("Use TryParse overload with 'ignoreCase' parameter")] public static NoNamespace? TryParse(string? name, StringComparison comparisonType) { - return TryParse(name, comparisonType, out NoNamespace result) ? result : null; + return TryParseName(name.AsSpan(), comparisonType, throwOnFailure: false, out var result) ? (NoNamespace?)result : null; } /// Retrieves an array of the values of the constants in the NoNamespace enumeration. @@ -275,10 +356,4 @@ public static string[] GetNames() "Two", }; } - - [DoesNotReturn] - private static void ThrowArgumentNullException(string paramName) - { - throw new ArgumentNullException(paramName); - } } diff --git a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceValidation.g.cs b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceValidation.g.cs index 176358a..e807899 100644 --- a/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceValidation.g.cs +++ b/tests/EnumUtilities.Generators.IntegrationTests/Generated/Raiqub.Generators.EnumUtilities/Raiqub.Generators.EnumUtilities.EnumUtilitiesGenerator/_.NoNamespaceValidation.g.cs @@ -7,7 +7,7 @@ #pragma warning disable CS1591 // publicly visible type or member must be documented [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.8.0.0")] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Raiqub.Generators.EnumUtilities", "1.9.0.0")] public static partial class NoNamespaceValidation { /// Returns a boolean telling whether the value of instance exists in the enumeration. diff --git a/version.json b/version.json index b95f3d1..b940a29 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json", - "version": "1.8", + "version": "1.9", "publicReleaseRefSpec": [ "^refs/tags/v\\d+\\.\\d+" ],