void IProtoSerializer.EmitRead(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { Type expected = ExpectedType; Helpers.DebugAssert(valueFrom != null); using (Compiler.Local loc = ctx.GetLocalWithValue(expected, valueFrom)) using (Compiler.Local fieldNumber = new Compiler.Local(ctx, ctx.MapType(typeof(int)))) { // pre-callbacks if (HasCallbacks(TypeModel.CallbackType.BeforeDeserialize)) { if (ExpectedType.IsValueType) { EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.BeforeDeserialize); } else { // could be null Compiler.CodeLabel callbacksDone = ctx.DefineLabel(); ctx.LoadValue(loc); ctx.BranchIfFalse(callbacksDone, false); EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.BeforeDeserialize); ctx.MarkLabel(callbacksDone); } } Compiler.CodeLabel @continue = ctx.DefineLabel(), processField = ctx.DefineLabel(); ctx.Branch(@continue, false); ctx.MarkLabel(processField); foreach (BasicList.Group group in BasicList.GetContiguousGroups(fieldNumbers, serializers)) { Compiler.CodeLabel tryNextField = ctx.DefineLabel(); int groupItemCount = group.Items.Count; if (groupItemCount == 1) { // discreet group; use an equality test ctx.LoadValue(fieldNumber); ctx.LoadValue(group.First); Compiler.CodeLabel processThisField = ctx.DefineLabel(); ctx.BranchIfEqual(processThisField, true); ctx.Branch(tryNextField, false); WriteFieldHandler(ctx, expected, loc, processThisField, @continue, (IProtoSerializer)group.Items[0]); } else { // implement as a jump-table-based switch ctx.LoadValue(fieldNumber); ctx.LoadValue(group.First); ctx.Subtract(); // jump-tables are zero-based Compiler.CodeLabel[] jmp = new Compiler.CodeLabel[groupItemCount]; for (int i = 0; i < groupItemCount; i++) { jmp[i] = ctx.DefineLabel(); } ctx.Switch(jmp); // write the default... ctx.Branch(tryNextField, false); for (int i = 0; i < groupItemCount; i++) { WriteFieldHandler(ctx, expected, loc, jmp[i], @continue, (IProtoSerializer)group.Items[i]); } } ctx.MarkLabel(tryNextField); } EmitCreateIfNull(ctx, loc); ctx.LoadReaderWriter(); if (isExtensible) { ctx.LoadValue(loc); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("AppendExtensionData")); } else { ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField")); } ctx.MarkLabel(@continue); ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int))); ctx.CopyValue(); ctx.StoreValue(fieldNumber); ctx.LoadValue(0); ctx.BranchIfGreater(processField, false); EmitCreateIfNull(ctx, loc); // post-callbacks EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.AfterDeserialize); if (valueFrom != null && !loc.IsSame(valueFrom)) { ctx.LoadValue(loc); ctx.Cast(valueFrom.Type); ctx.StoreValue(valueFrom); } } }
void IProtoSerializer.EmitRead(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { ProtoTypeCode typeCode = GetTypeCode(); if (map == null) { ctx.EmitBasicRead("ReadInt32", ctx.MapType(typeof(int))); ctx.ConvertFromInt32(typeCode, false); } else { int[] wireValues = new int[map.Length]; object[] values = new object[map.Length]; for (int i = 0; i < map.Length; i++) { wireValues[i] = map[i].WireValue; values[i] = map[i].RawValue; } using (Compiler.Local result = new Compiler.Local(ctx, ExpectedType)) using (Compiler.Local wireValue = new Compiler.Local(ctx, ctx.MapType(typeof(int)))) { ctx.EmitBasicRead("ReadInt32", ctx.MapType(typeof(int))); ctx.StoreValue(wireValue); Compiler.CodeLabel @continue = ctx.DefineLabel(); foreach (BasicList.Group group in BasicList.GetContiguousGroups(wireValues, values)) { Compiler.CodeLabel tryNextGroup = ctx.DefineLabel(); int groupItemCount = group.Items.Count; if (groupItemCount == 1) { // discreet group; use an equality test ctx.LoadValue(wireValue); ctx.LoadValue(group.First); Compiler.CodeLabel processThisValue = ctx.DefineLabel(); ctx.BranchIfEqual(processThisValue, true); ctx.Branch(tryNextGroup, false); WriteEnumValue(ctx, typeCode, processThisValue, @continue, group.Items[0], @result); } else { // implement as a jump-table-based switch ctx.LoadValue(wireValue); ctx.LoadValue(group.First); ctx.Subtract(); // jump-tables are zero-based Compiler.CodeLabel[] jmp = new Compiler.CodeLabel[groupItemCount]; for (int i = 0; i < groupItemCount; i++) { jmp[i] = ctx.DefineLabel(); } ctx.Switch(jmp); // write the default... ctx.Branch(tryNextGroup, false); for (int i = 0; i < groupItemCount; i++) { WriteEnumValue(ctx, typeCode, jmp[i], @continue, group.Items[i], @result); } } ctx.MarkLabel(tryNextGroup); } // throw source.CreateEnumException(ExpectedType, wireValue); ctx.LoadReaderWriter(); ctx.LoadValue(ExpectedType); ctx.LoadValue(wireValue); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("ThrowEnumException")); ctx.MarkLabel(@continue); ctx.LoadValue(result); } } }
void IProtoSerializer.EmitRead(CompilerContext ctx, Local valueFrom) { Type expectedType = this.ExpectedType; using (Local local = ctx.GetLocalWithValue(expectedType, valueFrom)) { using (Local local2 = new Local(ctx, ctx.MapType(typeof(int)))) { if (this.HasCallbacks(TypeModel.CallbackType.BeforeDeserialize)) { if (this.ExpectedType.IsValueType) { this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.BeforeDeserialize); } else { CodeLabel label = ctx.DefineLabel(); ctx.LoadValue(local); ctx.BranchIfFalse(label, false); this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.BeforeDeserialize); ctx.MarkLabel(label); } } CodeLabel label2 = ctx.DefineLabel(); CodeLabel label3 = ctx.DefineLabel(); ctx.Branch(label2, false); ctx.MarkLabel(label3); BasicList.NodeEnumerator enumerator = BasicList.GetContiguousGroups(this.fieldNumbers, this.serializers).GetEnumerator(); while (enumerator.MoveNext()) { BasicList.Group current = (BasicList.Group)enumerator.Current; CodeLabel label4 = ctx.DefineLabel(); int count = current.Items.Count; if (count == 1) { ctx.LoadValue(local2); ctx.LoadValue(current.First); CodeLabel label5 = ctx.DefineLabel(); ctx.BranchIfEqual(label5, true); ctx.Branch(label4, false); this.WriteFieldHandler(ctx, expectedType, local, label5, label2, (IProtoSerializer)current.Items[0]); } else { ctx.LoadValue(local2); ctx.LoadValue(current.First); ctx.Subtract(); CodeLabel[] jumpTable = new CodeLabel[count]; for (int i = 0; i < count; i++) { jumpTable[i] = ctx.DefineLabel(); } ctx.Switch(jumpTable); ctx.Branch(label4, false); for (int j = 0; j < count; j++) { this.WriteFieldHandler(ctx, expectedType, local, jumpTable[j], label2, (IProtoSerializer)current.Items[j]); } } ctx.MarkLabel(label4); } this.EmitCreateIfNull(ctx, local); ctx.LoadReaderWriter(); if (this.isExtensible) { ctx.LoadValue(local); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("AppendExtensionData")); } else { ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField")); } ctx.MarkLabel(label2); ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int))); ctx.CopyValue(); ctx.StoreValue(local2); ctx.LoadValue(0); ctx.BranchIfGreater(label3, false); this.EmitCreateIfNull(ctx, local); this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.AfterDeserialize); if ((valueFrom != null) && !local.IsSame(valueFrom)) { ctx.LoadValue(local); ctx.Cast(valueFrom.Type); ctx.StoreValue(valueFrom); } } } }
void IProtoSerializer.EmitRead(CompilerContext ctx, Local valueFrom) { ProtoTypeCode typeCode = this.GetTypeCode(); if (this.map == null) { ctx.EmitBasicRead("ReadInt32", ctx.MapType(typeof(int))); ctx.ConvertFromInt32(typeCode, false); } else { int[] keys = new int[this.map.Length]; object[] values = new object[this.map.Length]; for (int i = 0; i < this.map.Length; i++) { keys[i] = this.map[i].WireValue; values[i] = this.map[i].RawValue; } using (Local local = new Local(ctx, this.ExpectedType)) { using (Local local2 = new Local(ctx, ctx.MapType(typeof(int)))) { ctx.EmitBasicRead("ReadInt32", ctx.MapType(typeof(int))); ctx.StoreValue(local2); CodeLabel label = ctx.DefineLabel(); BasicList.NodeEnumerator enumerator = BasicList.GetContiguousGroups(keys, values).GetEnumerator(); while (enumerator.MoveNext()) { BasicList.Group current = (BasicList.Group)enumerator.Current; CodeLabel label2 = ctx.DefineLabel(); int count = current.Items.Count; if (count == 1) { ctx.LoadValue(local2); ctx.LoadValue(current.First); CodeLabel label3 = ctx.DefineLabel(); ctx.BranchIfEqual(label3, true); ctx.Branch(label2, false); WriteEnumValue(ctx, typeCode, label3, label, current.Items[0], local); } else { ctx.LoadValue(local2); ctx.LoadValue(current.First); ctx.Subtract(); CodeLabel[] jumpTable = new CodeLabel[count]; for (int j = 0; j < count; j++) { jumpTable[j] = ctx.DefineLabel(); } ctx.Switch(jumpTable); ctx.Branch(label2, false); for (int k = 0; k < count; k++) { WriteEnumValue(ctx, typeCode, jumpTable[k], label, current.Items[k], local); } } ctx.MarkLabel(label2); } ctx.LoadReaderWriter(); ctx.LoadValue(this.ExpectedType); ctx.LoadValue(local2); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("ThrowEnumException")); ctx.MarkLabel(label); ctx.LoadValue(local); } } } }
void ProtoBuf.Serializers.IProtoSerializer.EmitRead(CompilerContext ctx, Local valueFrom) { ProtoTypeCode typeCode = this.GetTypeCode(); if (this.map == null) { ctx.EmitBasicRead("ReadInt32", ctx.MapType(typeof(int))); ctx.ConvertFromInt32(typeCode, false); return; } int[] wireValue = new int[(int)this.map.Length]; object[] rawValue = new object[(int)this.map.Length]; for (int i = 0; i < (int)this.map.Length; i++) { wireValue[i] = this.map[i].WireValue; rawValue[i] = this.map[i].RawValue; } using (Local local = new Local(ctx, this.ExpectedType)) { using (Local local1 = new Local(ctx, ctx.MapType(typeof(int)))) { ctx.EmitBasicRead("ReadInt32", ctx.MapType(typeof(int))); ctx.StoreValue(local1); CodeLabel codeLabel = ctx.DefineLabel(); BasicList.NodeEnumerator enumerator = BasicList.GetContiguousGroups(wireValue, rawValue).GetEnumerator(); while (enumerator.MoveNext()) { BasicList.Group current = (BasicList.Group)enumerator.Current; CodeLabel codeLabel1 = ctx.DefineLabel(); int count = current.Items.Count; if (count != 1) { ctx.LoadValue(local1); ctx.LoadValue(current.First); ctx.Subtract(); CodeLabel[] codeLabelArray = new CodeLabel[count]; for (int j = 0; j < count; j++) { codeLabelArray[j] = ctx.DefineLabel(); } ctx.Switch(codeLabelArray); ctx.Branch(codeLabel1, false); for (int k = 0; k < count; k++) { EnumSerializer.WriteEnumValue(ctx, typeCode, codeLabelArray[k], codeLabel, current.Items[k], local); } } else { ctx.LoadValue(local1); ctx.LoadValue(current.First); CodeLabel codeLabel2 = ctx.DefineLabel(); ctx.BranchIfEqual(codeLabel2, true); ctx.Branch(codeLabel1, false); EnumSerializer.WriteEnumValue(ctx, typeCode, codeLabel2, codeLabel, current.Items[0], local); } ctx.MarkLabel(codeLabel1); } ctx.LoadReaderWriter(); ctx.LoadValue(this.ExpectedType); ctx.LoadValue(local1); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("ThrowEnumException")); ctx.MarkLabel(codeLabel); ctx.LoadValue(local); } } }