Skip to content

Commit 8a5a0ae

Browse files
author
machibuse
committed
Rename Porticle.Grpc.GuidMapper to Porticle.Grpc.TypeMapper, update README, namespaces, and project references to reflect new functionality and naming. Add support for nullable enums and enhance documentation with examples and usage details.
1 parent 99d0d74 commit 8a5a0ae

19 files changed

Lines changed: 138 additions & 43 deletions

.github/workflows/release.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
run: dotnet test Source/Porticle.Grpc.UnitTests/Porticle.Grpc.UnitTests.csproj --configuration Release --no-build --verbosity normal
3535

3636
- name: Pack NuGet package
37-
run: dotnet pack Source/Porticle.Grpc.GuidMapper/Porticle.Grpc.GuidMapper.csproj --configuration Release --no-build --output ./nuget --property:PackageVersion=${{ env.VERSION }}
37+
run: dotnet pack Source/Porticle.Grpc.TypeMapper/Porticle.Grpc.TypeMapper.csproj --configuration Release --no-build --output ./nuget --property:PackageVersion=${{ env.VERSION }}
3838

3939
- name: Publish NuGet package
4040
run: dotnet nuget push ./nuget/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
@@ -44,7 +44,7 @@ jobs:
4444
with:
4545
tag_name: v${{ env.VERSION }}
4646
name: Release v${{ env.VERSION }}
47-
body: "Nuget Release für Porticle.Grpc.GuidMapper v${{ env.VERSION }}."
47+
body: "Nuget Release für Porticle.Grpc.TypeMapper v${{ env.VERSION }}."
4848
files: ./nuget/*.nupkg
4949
draft: false
5050
prerelease: ${{ contains(env.VERSION, '-beta') || contains(env.VERSION, '-alpha') || contains(env.VERSION, '-rc') }}

README.md

Lines changed: 108 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
1-
# Porticle.Grpc.GuidMapper
1+
# Porticle.Grpc.TypeMapper
22

3-
A Roslyn-based post-processor for protoc-generated files that adds native Guid, Guid? and string? types in gRPC services.
3+
A Roslyn-based post-processor for protoc-generated files that adds automatic mappings for
4+
5+
6+
7+
and vice versa.
48

59
## Build State
610

7-
[![Build and Release](https://github.com/Machibuse/Porticle.Grpc.GuidMapper/actions/workflows/release.yaml/badge.svg)](https://github.com/Machibuse/Porticle.CLDR/actions/workflows/release.yaml)
11+
[![Build and Release](https://github.com/Machibuse/Porticle.Grpc.TypeMapper/actions/workflows/release.yaml/badge.svg)](https://github.com/Machibuse/Porticle.CLDR/actions/workflows/release.yaml)
812

913
## Nuget
1014

11-
[![NuGet Latest Version](https://img.shields.io/nuget/v/Porticle.Grpc.GuidMapper.svg)](https://www.nuget.org/packages/Porticle.Grpc.GuidMapper/) [![NuGet Downloads](https://img.shields.io/nuget/dt/Porticle.Grpc.GuidMapper.svg)](https://www.nuget.org/packages/Porticle.CLDR.Units/)
15+
[![NuGet Latest Version](https://img.shields.io/nuget/v/Porticle.Grpc.TypeMapper.svg)](https://www.nuget.org/packages/Porticle.Grpc.TypeMapper/) [![NuGet Downloads](https://img.shields.io/nuget/dt/Porticle.Grpc.TypeMapper.svg)](https://www.nuget.org/packages/Porticle.CLDR.Units/)
1216

1317
## Overview
1418

15-
This library allows you to automatically convert PROTO string or StringValue fields to C# Guid, Guid? or string? types in protoc-generated files, enabling seamless integration of
16-
GUIDs in your gRPC services without manual conversion
19+
This library adds automatic conversion for:
20+
21+
- Protobuf string to C# Guid
22+
- Protobuf google.Protobuf.StringValue to C# Guid?
23+
- Protobuf google.Protobuf.StringValue to C# string?
24+
- Protobuf optional enum to C# nullable enum
25+
26+
This Library adds a Roslyn Postprocessing zu the c# files generated by the protoc compiler.
27+
Enabling seamless integration of Guid, Guid?, string? and nullable Enums in your gRPC services without manual conversion.
1728
code.
1829

1930
## Installation
2031

2132
### Install the package via NuGet:
2233

2334
```powershell
24-
dotnet add package Porticle.Grpc.GuidMapper
35+
dotnet add package Porticle.Grpc.TypeMapper
2536
```
2637

2738
After installing the Package, this Post build step ist dynamically added to your build.
@@ -33,7 +44,7 @@ After installing the Package, this Post build step ist dynamically added to your
3344
<_FilesToPostProcess Include="$(MSBuildProjectDirectory)\%(Protobuf_Compile.OutputDir)\%(Protobuf_Compile.Filename)" />
3445
</ItemGroup>
3546
<Message Text="Proto Postprocessing" Importance="high" />
36-
<Exec Command="dotnet &quot;$(MSBuildThisFileDirectory)..\tools\$(TargetFramework)\Porticle.Grpc.GuidMapper.dll&quot; -- %(_FilesToPostProcess.Identity)" Condition="'@(_FilesToPostProcess)' != ''" />
47+
<Exec Command="dotnet &quot;$(MSBuildThisFileDirectory)..\tools\$(TargetFramework)\Porticle.Grpc.TypeMapper.dll&quot; -- %(_FilesToPostProcess.Identity)" Condition="'@(_FilesToPostProcess)' != ''" />
3748
</Target>
3849
</Project>
3950
```
@@ -47,16 +58,22 @@ There are three things you can do in your .proto files:
4758
- Add `// [GrpcGuid]` as comment to a string field - Converts the corresponding c# string property to Guid
4859
- Add `// [GrpcGuid]` as comment to a StringValue field - Converts the corresponding c# string property to Guid?
4960
- Add `// [NullableString]` as comment to a StringValue field - Converts the corresponding c# string property to string?
61+
- Add `// [NullableEnum]` as comment to a optional enum field - Converts the corresponding optional proto enum to a C# nullable Enum
5062

5163
First an Example of a default .proto file
5264

53-
### Without GuidMapper
65+
### Without TypeMapper
5466

5567
```protobuf
5668
syntax = "proto3";
5769
5870
import "google/protobuf/wrappers.proto";
5971
72+
enum TestEnum {
73+
FOO = 0;
74+
BAR = 1;
75+
}
76+
6077
message User {
6178
// Guid of the user object
6279
string id = 1;
@@ -69,10 +86,13 @@ message User {
6986
7087
// List of roles
7188
repeated string role_ids = 4;
89+
90+
// Simple Enum
91+
optional TestEnum foo_bar = 5;
7292
}
7393
```
7494

75-
Will result in generated code like this, everything is a string
95+
Will result in protoc generated code like this, everything is a string or a simple enum
7696

7797
```csharp
7898
/// <summary>Guid of the user object</summary>
@@ -97,15 +117,33 @@ public string Description {
97117
public pbc::RepeatedField<string> RoleIds {
98118
get { return roleIds_; }
99119
}
120+
121+
public global::Porticle.Grpc.UnitTests.TestEnum FooBar {
122+
get {
123+
if ((_hasBits0 & 1) != 0)
124+
return fooBar_;
125+
else
126+
return FooBarDefaultValue;
127+
}
128+
set {
129+
_hasBits0 |= 1;
130+
fooBar_ = value;
131+
}
132+
}
100133
```
101134

102-
### With GuidMapper
135+
### Now a sample with TypeMapper enabled
103136

104137
```protobuf
105138
syntax = "proto3";
106139
107140
import "google/protobuf/wrappers.proto";
108141
142+
enum TestEnum {
143+
FOO = 0;
144+
BAR = 1;
145+
}
146+
109147
message User {
110148
// [GrpcGuid] Guid of the user object
111149
string id = 1;
@@ -118,25 +156,46 @@ message User {
118156
119157
// [GrpcGuid] List of roles
120158
repeated string role_ids = 4;
159+
160+
// [NullableEnum] Simple Enum
161+
optional TestEnum foo_bar = 5;
121162
}
122163
```
123164

124-
Will result in generated code like this, using string? Guid and Guid?
165+
Will result in generated code like this, using string? Guid and Guid? and a nullable Enum
125166

126167
```csharp
127168
/// <summary>[GrpcGuid] Guid of the user object</summary>
128169
public global::System.Guid Id {
129-
get { return global::System.Guid.Parse(id_); }
130-
set { id_ = (value).ToString("D"); }
170+
get
171+
{
172+
// Parse the internal string as Guid and return it
173+
return global::System.Guid.Parse(id_);
174+
}
175+
set
176+
{
177+
// Set the internal string fron the given guid
178+
id_ = (value).ToString("D");
179+
}
131180
}
132181

133182
/// <summary>[GrpcGuid] Optional Guid of the parent UserId</summary>
134183
public global::System.Guid? OptionalParentUserId {
135-
get { if(optionalParentUserId_==null) return default; return global::System.Guid.Parse(optionalParentUserId_); }
136-
set { optionalParentUserId_ = (value)?.ToString("D"); }
184+
get {
185+
// return null wehn corresponding string is null
186+
if(optionalParentUserId_==null) return default;
187+
// return a Guid instead of the string
188+
return global::System.Guid.Parse(optionalParentUserId_);
189+
}
190+
set
191+
{
192+
// sets the internal string from the given guid
193+
optionalParentUserId_ = (value)?.ToString("D");
194+
}
137195
}
138196

139197

198+
// enable nullable for this property and return string? instead of string
140199
#nullable enable
141200
/// <summary>[NullableString] Optional description string</summary>
142201
public string? Description {
@@ -147,13 +206,43 @@ public string? Description {
147206

148207
/// <summary>[GrpcGuid] List of roles</summary>
149208
public IList<Guid> RoleIds {
150-
get {return new RepeatedFieldGuidWrapper(roleIds_); }
209+
get
210+
{
211+
// returns a wrapper that converts a list of strings to a list of guids
212+
return new RepeatedFieldGuidWrapper(roleIds_);
213+
}
214+
}
215+
216+
public global::Porticle.Grpc.UnitTests.TestEnum? FooBar {
217+
get {
218+
if ((_hasBits0 & 1) != 0)
219+
{
220+
return fooBar_;
221+
}
222+
else
223+
{
224+
// return null instead of default value when Has-Flag is false
225+
return null;
226+
}
227+
}
228+
set {
229+
if(value==null) {
230+
// Set hasflag to false when null is assigend
231+
_hasBits0 &=~1;
232+
fooBar_ = FooBarDefaultValue;
233+
}
234+
else
235+
{
236+
_hasBits0 |= 1;
237+
fooBar_ = value.Value;
238+
}
239+
}
151240
}
152241
```
153242

154-
## What currently is not Possible?
243+
## What is currently not Possible?
155244

156245
- Mapping `repeated google.protobuf.StringValue` to `List<Guid?>` or `List<string?>` because grpc internally uses `RepeatedField<string>` instead of `RepeatedField<StringValue>`.
157-
This may be a bug in protoc compiler, because it is also not possible to add `null` to `repeated google.protobuf.StringValue` because ther is a not null check in the Add function in `RepeatedField<T>`
246+
This may be a bug in protoc compiler, because it is also not possible to add `null` to `repeated google.protobuf.StringValue` because there is a not null check in the Add function in `RepeatedField<T>`
158247

159248
- This Tool actually don't works when protoc / Grpc.Tools is compiled with GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE

Source/Porticle.Grpc.GuidMapper/ClassVisitor.cs renamed to Source/Porticle.Grpc.TypeMapper/ClassVisitor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
using Microsoft.CodeAnalysis.CSharp;
33
using Microsoft.CodeAnalysis.CSharp.Syntax;
44

5-
namespace Porticle.Grpc.GuidMapper;
5+
namespace Porticle.Grpc.TypeMapper;
66

77
public class ClassVisitor : CSharpSyntaxRewriter
88
{
99
public override SyntaxNode? VisitClassDeclaration(ClassDeclarationSyntax node)
1010
{
11-
var marker = "[Porticle.Grpc.GuidMapper]";
11+
var marker = "[Porticle.Grpc.TypeMapper]";
1212

1313
if (node.GetLeadingTrivia().ToFullString().Contains(marker))
1414
// Skip if marker exists - class alreqady patched

Source/Porticle.Grpc.GuidMapper/Extensions.cs renamed to Source/Porticle.Grpc.TypeMapper/Extensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using Microsoft.CodeAnalysis.CSharp;
33
using Microsoft.CodeAnalysis.CSharp.Syntax;
44

5-
namespace Porticle.Grpc.GuidMapper;
5+
namespace Porticle.Grpc.TypeMapper;
66

77
public static class Extensions
88
{

Source/Porticle.Grpc.GuidMapper/ListWrappers.cs renamed to Source/Porticle.Grpc.TypeMapper/ListWrappers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Porticle.Grpc.GuidMapper;
1+
namespace Porticle.Grpc.TypeMapper;
22

33
public static class ListWrappers
44
{

Source/Porticle.Grpc.GuidMapper/MethodVisitor.cs renamed to Source/Porticle.Grpc.TypeMapper/MethodVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using Microsoft.CodeAnalysis.CSharp;
33
using Microsoft.CodeAnalysis.CSharp.Syntax;
44

5-
namespace Porticle.Grpc.GuidMapper;
5+
namespace Porticle.Grpc.TypeMapper;
66

77
public class MethodVisitor : CSharpSyntaxRewriter
88
{

Source/Porticle.Grpc.GuidMapper/Porticle.Grpc.GuidMapper.csproj renamed to Source/Porticle.Grpc.TypeMapper/Porticle.Grpc.TypeMapper.csproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
<ImplicitUsings>enable</ImplicitUsings>
55
<Nullable>enable</Nullable>
66
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
7-
<Title>Porticle.CLDR.Units</Title>
7+
<Title>Porticle.Grpc.TypeMapper</Title>
88
<Authors>Carsten Jendro</Authors>
9-
<Description>Roslin postprocessor to map GRPC strings to Guids</Description>
9+
<Description>Roslin postprocessor to map GRPC properties to strings to Guids or nullable enums</Description>
1010
<Copyright>Carsten Jendro</Copyright>
11-
<PackageProjectUrl>https://github.com/Machibuse/Porticle.Grpc.GuidMapper</PackageProjectUrl>
11+
<PackageProjectUrl>https://github.com/Machibuse/Porticle.Grpc.TypeMapper</PackageProjectUrl>
1212
<PackageLicenseExpression>MIT</PackageLicenseExpression>
1313
<PackageIcon>pinky32.png</PackageIcon>
14-
<RepositoryUrl>https://github.com/Machibuse/Porticle.Grpc.GuidMapper.git</RepositoryUrl>
14+
<RepositoryUrl>https://github.com/Machibuse/Porticle.Grpc.TypeMapper.git</RepositoryUrl>
1515
<RepositoryType>git</RepositoryType>
16-
<PackageReleaseNotes>First test version</PackageReleaseNotes>
16+
<PackageReleaseNotes></PackageReleaseNotes>
1717
<IncludeBuildOutput>false</IncludeBuildOutput>
1818
<DevelopmentDependency>true</DevelopmentDependency>
1919
<Version>1.0.26</Version>
@@ -38,7 +38,7 @@
3838

3939
<ItemGroup>
4040
<None Include="..\..\readme.md" Pack="true" PackagePath="\"/>
41-
<None Include="Porticle.Grpc.GuidMapper.targets" Pack="true" PackagePath="buildTransitive"/>
41+
<None Include="Porticle.Grpc.TypeMapper.targets" Pack="true" PackagePath="buildTransitive" />
4242
<None Include="$(OutputPath)**\*" Pack="true" PackagePath="tools\$(TargetFramework)\"/>
4343
</ItemGroup>
4444
</Project>

Source/Porticle.Grpc.GuidMapper/Porticle.Grpc.GuidMapper.targets renamed to Source/Porticle.Grpc.TypeMapper/Porticle.Grpc.TypeMapper.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
<_FilesToPostProcess Include="$(MSBuildProjectDirectory)\%(Protobuf_Compile.OutputDir)\%(Protobuf_Compile.Filename)"/>
55
</ItemGroup>
66
<Message Text="Proto Postprocessing" Importance="high"/>
7-
<Exec Command="dotnet &quot;$(MSBuildThisFileDirectory)..\tools\$(TargetFramework)\Porticle.Grpc.GuidMapper.dll&quot; -- %(_FilesToPostProcess.Identity)" Condition="'@(_FilesToPostProcess)' != ''"/>
7+
<Exec Command="dotnet &quot;$(MSBuildThisFileDirectory)..\tools\$(TargetFramework)\Porticle.Grpc.TypeMapper.dll&quot; -- %(_FilesToPostProcess.Identity)" Condition="'@(_FilesToPostProcess)' != ''"/>
88
</Target>
99
</Project>

Source/Porticle.Grpc.GuidMapper/Program.cs renamed to Source/Porticle.Grpc.TypeMapper/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using Microsoft.CodeAnalysis.CSharp;
2-
using Porticle.Grpc.GuidMapper;
2+
using Porticle.Grpc.TypeMapper;
33

44
// filter out "--" arg
55
args = args.Where(s => s != "--").ToArray();

Source/Porticle.Grpc.GuidMapper/PropertyToField.cs renamed to Source/Porticle.Grpc.TypeMapper/PropertyToField.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Microsoft.CodeAnalysis.CSharp.Syntax;
22

3-
namespace Porticle.Grpc.GuidMapper;
3+
namespace Porticle.Grpc.TypeMapper;
44

55
/// <summary>
66
/// Represents a mapping between a property name and its corresponding field name.

0 commit comments

Comments
 (0)