Exemplo n.º 1
0
        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);
                    }
                }
        }
Exemplo n.º 2
0
        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);
                    }
            }
        }
Exemplo n.º 3
0
        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);
                    }
                }
            }
        }
Exemplo n.º 4
0
        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);
                    }
                }
            }
        }
Exemplo n.º 5
0
        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);
                }
            }
        }