Skip to content

Commit 7b8bd36

Browse files
committed
[Proto] Enhance Proto serialization to handle nullable types and improve ZigZag encoding
1 parent 18ca20f commit 7b8bd36

22 files changed

Lines changed: 3453 additions & 31 deletions

Lagrange.Proto.Generator/ProtoSourceGenerator.Emitter.Serialize.cs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@ private void EmitMember(SourceWriter source, int field, ProtoFieldInfo info, str
118118
{
119119
string? special = info.WireType switch
120120
{
121-
WireType.VarInt when info.TypeSymbol.IsIntegerType() && info.IsSigned => $"{WriterVarName}.{EncodeVarIntMethodName}({ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
121+
WireType.VarInt when info.TypeSymbol.IsIntegerType() && info.IsSigned => GetZigZagEncodeCall(info.TypeSymbol, memberName),
122122
WireType.VarInt when info.TypeSymbol.IsIntegerType() => $"{WriterVarName}.{EncodeVarIntMethodName}({memberName});",
123-
WireType.Fixed32 when info.IsSigned => $"{WriterVarName}.{EncodeFixed32MethodName}({ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
124-
WireType.Fixed64 when info.IsSigned => $"{WriterVarName}.{EncodeFixed64MethodName}({ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
123+
WireType.Fixed32 when info.IsSigned => GetZigZagEncodeFixed32Call(info.TypeSymbol, memberName),
124+
WireType.Fixed64 when info.IsSigned => GetZigZagEncodeFixed64Call(info.TypeSymbol, memberName),
125125
WireType.Fixed32 => $"{WriterVarName}.{EncodeFixed32MethodName}({memberName});",
126126
WireType.Fixed64 => $"{WriterVarName}.{EncodeFixed64MethodName}({memberName});",
127127
WireType.LengthDelimited when info.TypeSymbol.SpecialType == SpecialType.System_String => $"{WriterVarName}.{EncodeStringMethodName}({memberName});",
@@ -170,5 +170,39 @@ private void EmitIfShouldSerializeStatement(SourceWriter source, int tag, Action
170170
source.Indentation--;
171171
source.WriteLine("}");
172172
}
173+
174+
private string GetZigZagEncodeCall(ITypeSymbol typeSymbol, string memberName)
175+
{
176+
// For signed byte types, we need to cast the ZigZag encoded result to unsigned
177+
// to prevent sign extension when writing as varint
178+
return typeSymbol.SpecialType switch
179+
{
180+
SpecialType.System_SByte => $"{WriterVarName}.{EncodeVarIntMethodName}((byte){ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
181+
SpecialType.System_Int16 => $"{WriterVarName}.{EncodeVarIntMethodName}((ushort){ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
182+
SpecialType.System_Int32 => $"{WriterVarName}.{EncodeVarIntMethodName}((uint){ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
183+
SpecialType.System_Int64 => $"{WriterVarName}.{EncodeVarIntMethodName}((ulong){ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
184+
_ => $"{WriterVarName}.{EncodeVarIntMethodName}({ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));"
185+
};
186+
}
187+
188+
private string GetZigZagEncodeFixed32Call(ITypeSymbol typeSymbol, string memberName)
189+
{
190+
return typeSymbol.SpecialType switch
191+
{
192+
SpecialType.System_SByte => $"{WriterVarName}.{EncodeFixed32MethodName}((byte){ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
193+
SpecialType.System_Int16 => $"{WriterVarName}.{EncodeFixed32MethodName}((ushort){ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
194+
SpecialType.System_Int32 => $"{WriterVarName}.{EncodeFixed32MethodName}((uint){ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
195+
_ => $"{WriterVarName}.{EncodeFixed32MethodName}({ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));"
196+
};
197+
}
198+
199+
private string GetZigZagEncodeFixed64Call(ITypeSymbol typeSymbol, string memberName)
200+
{
201+
return typeSymbol.SpecialType switch
202+
{
203+
SpecialType.System_Int64 => $"{WriterVarName}.{EncodeFixed64MethodName}((ulong){ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));",
204+
_ => $"{WriterVarName}.{EncodeFixed64MethodName}({ProtoHelperTypeRef}.{ZigZagEncodeMethodName}({memberName}));"
205+
};
206+
}
173207
}
174208
}

Lagrange.Proto.Generator/Utility/ProtoHelper.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public static byte[] EncodeVarInt(int value)
2424
public static WireType GetWireType(ITypeSymbol symbol)
2525
{
2626
if (SymbolResolver.IsRepeatedType(symbol, out var type)) symbol = type;
27+
if (SymbolResolver.IsNullableType(symbol, out var elementType)) symbol = elementType;
2728

2829
if (symbol.IsIntegerType() || symbol.TypeKind == TypeKind.Enum || symbol.SpecialType == SpecialType.System_Boolean) return WireType.VarInt;
2930
if (symbol.SpecialType == SpecialType.System_Single) return WireType.Fixed32;

0 commit comments

Comments
 (0)