Skip to content

Commit

Permalink
Fix assignment tracking (#166)
Browse files Browse the repository at this point in the history
Fixes incorrect handling of skipping fields
  • Loading branch information
agocke authored Jun 15, 2024
1 parent 015ea73 commit e64bfb7
Show file tree
Hide file tree
Showing 42 changed files with 178 additions and 83 deletions.
27 changes: 20 additions & 7 deletions src/generator/Generator.Deserialize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ private static MethodDeclarationSyntax GenerateCustomDeserializeMethod(
<= 64 => "ulong",
_ => throw new InvalidOperationException("Too many members in type")
};
var (cases, locals, assignedMask) = InitCasesAndLocals();
string typeCreationExpr = GenerateTypeCreation(context, typeFqn, type, members);
var (cases, locals, requiredMask) = InitCasesAndLocals();
string typeCreationExpr = GenerateTypeCreation(context, typeFqn, type, members, requiredMask);

const string typeInfoLocalName = "_l_typeInfo";
const string indexLocalName = "_l_index_";
Expand All @@ -96,7 +96,7 @@ private static MethodDeclarationSyntax GenerateCustomDeserializeMethod(
static {{typeFqn}} Serde.IDeserialize<{{typeFqn}}>.Deserialize(IDeserializer deserializer)
{
{{locals}}
{{assignedVarType}} {{AssignedVarName}} = {{assignedMask}};
{{assignedVarType}} {{AssignedVarName}} = 0;

var {{typeInfoLocalName}} = {{type.Name}}SerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType({{typeInfoLocalName}});
Expand All @@ -119,10 +119,12 @@ private static MethodDeclarationSyntax GenerateCustomDeserializeMethod(
var casesBuilder = new StringBuilder();
var localsBuilder = new StringBuilder();
long assignedMaskValue = 0;
var skippedIndices = new List<int>();
for (int i = 0; i < members.Count; i++)
{
if (members[i].SkipDeserialize)
{
skippedIndices.Add(i);
continue;
}

Expand Down Expand Up @@ -160,7 +162,7 @@ private static MethodDeclarationSyntax GenerateCustomDeserializeMethod(
{AssignedVarName} |= (({assignedVarType})1) << {i};
break;
""");
if (m.IsNullable && !m.ThrowIfMissing)
if (!m.IsNullable || m.ThrowIfMissing)
{
assignedMaskValue |= 1L << i;
}
Expand All @@ -170,6 +172,12 @@ private static MethodDeclarationSyntax GenerateCustomDeserializeMethod(
throw new InvalidDeserializeValueException("Unexpected field or property name in type {type.Name}: '" + _l_errorName + "'");
"""
: "break;";
foreach (var i in skippedIndices)
{
casesBuilder.AppendLine($"""
case {i}:
""");
}
casesBuilder.AppendLine($"""
case Serde.IDeserializeType.IndexNotFound:
{unknownMemberBehavior}
Expand Down Expand Up @@ -452,7 +460,7 @@ private static MemberDeclarationSyntax GenerateCustomTypeVisitor(
_ => throw new InvalidOperationException("Too many members in type")
};
var (cases, locals, assignedMask) = InitCasesAndLocals();
string typeCreationExpr = GenerateTypeCreation(context, typeName, type, members);
string typeCreationExpr = GenerateTypeCreation(context, typeName, type, members, assignedMask);
var methodText = $$"""
{{typeName}} Serde.IDeserializeVisitor<{{typeName}}>.VisitDictionary<D>(ref D d)
{
Expand Down Expand Up @@ -529,7 +537,12 @@ private static MemberDeclarationSyntax GenerateCustomTypeVisitor(
/// must be a constructor signature as specified by the ConstructorSignature property
/// in the SerdeTypeOptions.
/// </summary>
private static string GenerateTypeCreation(GeneratorExecutionContext context, string typeName, ITypeSymbol type, List<DataMemberSymbol> members)
private static string GenerateTypeCreation(
GeneratorExecutionContext context,
string typeName,
ITypeSymbol type,
List<DataMemberSymbol> members,
string assignedMask)
{
var targetSignature = SymbolUtilities.GetTypeOptions(type).ConstructorSignature;
var targetTuple = targetSignature as INamedTypeSymbol;
Expand Down Expand Up @@ -602,7 +615,7 @@ private static string GenerateTypeCreation(GeneratorExecutionContext context, st
}
var mask = new string('1', members.Count);
return $$"""
if ({{AssignedVarName}} != 0b{{mask}})
if (({{AssignedVarName}} & {{assignedMask}}) != {{assignedMask}})
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ partial record AllInOne : Serde.IDeserialize<Serde.Test.AllInOne>
int[][] _l_nestedarr = default !;
System.Collections.Immutable.ImmutableArray<int> _l_intimm = default !;
Serde.Test.AllInOne.ColorEnum _l_color = default !;
ushort _r_assignedValid = 0b100000000000;
ushort _r_assignedValid = 0;
var _l_typeInfo = AllInOneSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand Down Expand Up @@ -105,7 +105,7 @@ partial record AllInOne : Serde.IDeserialize<Serde.Test.AllInOne>
}
}

if (_r_assignedValid != 0b1111111111111111)
if ((_r_assignedValid & 0b1111011111111111) != 0b1111011111111111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ static C Serde.IDeserialize<C>.Deserialize(IDeserializer deserializer)
ColorByte _l_colorbyte = default !;
ColorLong _l_colorlong = default !;
ColorULong _l_colorulong = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = CSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand Down Expand Up @@ -43,7 +43,7 @@ static C Serde.IDeserialize<C>.Deserialize(IDeserializer deserializer)
}
}

if (_r_assignedValid != 0b1111)
if ((_r_assignedValid & 0b1111) != 0b1111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ partial record struct OptsWrap : Serde.IDeserialize<System.Runtime.InteropServic
int _l_dwtickcountdeadline = default !;
int _l_grfflags = default !;
int _l_grfmode = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = BIND_OPTSSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand Down Expand Up @@ -43,7 +43,7 @@ partial record struct OptsWrap : Serde.IDeserialize<System.Runtime.InteropServic
}
}

if (_r_assignedValid != 0b1111)
if ((_r_assignedValid & 0b1111) != 0b1111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ partial struct S : Serde.IDeserialize<S>
static S Serde.IDeserialize<S>.Deserialize(IDeserializer deserializer)
{
System.Collections.Immutable.ImmutableArray<System.Runtime.InteropServices.ComTypes.BIND_OPTS> _l_opts = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = SSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -28,7 +28,7 @@ static S Serde.IDeserialize<S>.Deserialize(IDeserializer deserializer)
}
}

if (_r_assignedValid != 0b1)
if ((_r_assignedValid & 0b1) != 0b1)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ partial class ArrayField : Serde.IDeserialize<ArrayField>
static ArrayField Serde.IDeserialize<ArrayField>.Deserialize(IDeserializer deserializer)
{
int[] _l_intarr = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = ArrayFieldSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -28,7 +28,7 @@ static ArrayField Serde.IDeserialize<ArrayField>.Deserialize(IDeserializer deser
}
}

if (_r_assignedValid != 0b1)
if ((_r_assignedValid & 0b1) != 0b1)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ static SetToNull Serde.IDeserialize<SetToNull>.Deserialize(IDeserializer deseria
string _l_present = default !;
string? _l_missing = default !;
string? _l_throwmissing = default !;
byte _r_assignedValid = 0b10;
byte _r_assignedValid = 0;
var _l_typeInfo = SetToNullSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -38,7 +38,7 @@ static SetToNull Serde.IDeserialize<SetToNull>.Deserialize(IDeserializer deseria
}
}

if (_r_assignedValid != 0b111)
if ((_r_assignedValid & 0b101) != 0b101)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ partial record struct Wrap : Serde.IDeserialize<System.Runtime.InteropServices.C
int _l_dwtickcountdeadline = default !;
int _l_grfflags = default !;
int _l_grfmode = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = BIND_OPTSSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand Down Expand Up @@ -43,7 +43,7 @@ partial record struct Wrap : Serde.IDeserialize<System.Runtime.InteropServices.C
}
}

if (_r_assignedValid != 0b1111)
if ((_r_assignedValid & 0b1111) != 0b1111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)
{
byte _l_red = default !;
byte _l_blue = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = RgbSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -33,7 +33,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)
}
}

if (_r_assignedValid != 0b11)
if ((_r_assignedValid & 0b11) != 0b11)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)
{
byte _l_red = default !;
byte _l_blue = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = RgbSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -26,14 +26,15 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)
_l_blue = typeDeserialize.ReadValue<byte, ByteWrap>(_l_index_);
_r_assignedValid |= ((byte)1) << 2;
break;
case 1:
case Serde.IDeserializeType.IndexNotFound:
break;
default:
throw new InvalidOperationException("Unexpected index: " + _l_index_);
}
}

if (_r_assignedValid != 0b111)
if ((_r_assignedValid & 0b101) != 0b101)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)
byte _l_red = default !;
byte _l_green = default !;
byte _l_blue = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = RgbSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -38,7 +38,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)
}
}

if (_r_assignedValid != 0b111)
if ((_r_assignedValid & 0b111) != 0b111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ partial class D : Serde.IDeserialize<A.B.C.D>
static A.B.C.D Serde.IDeserialize<A.B.C.D>.Deserialize(IDeserializer deserializer)
{
int _l_field = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = DSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -34,7 +34,7 @@ partial class D : Serde.IDeserialize<A.B.C.D>
}
}

if (_r_assignedValid != 0b1)
if ((_r_assignedValid & 0b1) != 0b1)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ partial struct S : Serde.IDeserialize<S>
static S Serde.IDeserialize<S>.Deserialize(IDeserializer deserializer)
{
string? _l_f = default !;
byte _r_assignedValid = 0b1;
byte _r_assignedValid = 0;
var _l_typeInfo = SSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -28,7 +28,7 @@ static S Serde.IDeserialize<S>.Deserialize(IDeserializer deserializer)
}
}

if (_r_assignedValid != 0b1)
if ((_r_assignedValid & 0b0) != 0b0)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)
byte _l_red = default !;
byte _l_green = default !;
byte _l_blue = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = RgbSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -38,7 +38,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)
}
}

if (_r_assignedValid != 0b111)
if ((_r_assignedValid & 0b111) != 0b111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ partial struct S : Serde.IDeserialize<S>
static S Serde.IDeserialize<S>.Deserialize(IDeserializer deserializer)
{
ColorEnum _l_e = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = SSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -28,7 +28,7 @@ static S Serde.IDeserialize<S>.Deserialize(IDeserializer deserializer)
}
}

if (_r_assignedValid != 0b1)
if ((_r_assignedValid & 0b1) != 0b1)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ partial struct S2 : Serde.IDeserialize<S2>
static S2 Serde.IDeserialize<S2>.Deserialize(IDeserializer deserializer)
{
ColorEnum _l_e = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = S2SerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -28,7 +28,7 @@ static S2 Serde.IDeserialize<S2>.Deserialize(IDeserializer deserializer)
}
}

if (_r_assignedValid != 0b1)
if ((_r_assignedValid & 0b1) != 0b1)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static S Serde.IDeserialize<S>.Deserialize(IDeserializer deserializer)
{
int _l_one = default !;
int _l_twoword = default !;
byte _r_assignedValid = 0b0;
byte _r_assignedValid = 0;
var _l_typeInfo = SSerdeTypeInfo.TypeInfo;
var typeDeserialize = deserializer.DeserializeType(_l_typeInfo);
int _l_index_;
Expand All @@ -33,7 +33,7 @@ static S Serde.IDeserialize<S>.Deserialize(IDeserializer deserializer)
}
}

if (_r_assignedValid != 0b11)
if ((_r_assignedValid & 0b11) != 0b11)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
}
Expand Down
Loading

0 comments on commit e64bfb7

Please sign in to comment.