Exemple #1
0
        internal void WriteNullCheckedTail(Type type, IProtoSerializer tail, Local valueFrom)
        {
            if (type.IsValueType)
            {
                if (Helpers.GetUnderlyingType(type) == null)
                {
                    tail.EmitWrite(this, valueFrom);
                    return;
                }
                using (Local local = this.GetLocalWithValue(type, valueFrom))
                {
                    this.LoadAddress(local, type);
                    this.LoadValue(type.GetProperty("HasValue"));
                    CodeLabel label = this.DefineLabel();
                    this.BranchIfFalse(label, false);
                    this.LoadAddress(local, type);
                    this.EmitCall(type.GetMethod("GetValueOrDefault", Helpers.EmptyTypes));
                    tail.EmitWrite(this, null);
                    this.MarkLabel(label);
                    return;
                }
            }
            this.LoadValue(valueFrom);
            this.CopyValue();
            CodeLabel label2 = this.DefineLabel();
            CodeLabel label3 = this.DefineLabel();

            this.BranchIfTrue(label2, true);
            this.DiscardValue();
            this.Branch(label3, false);
            this.MarkLabel(label2);
            tail.EmitWrite(this, null);
            this.MarkLabel(label3);
        }
        }                                                            // updates field directly
#if FEAT_COMPILER
        void IProtoSerializer.EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom)
        {
            Type expected = ExpectedType;

            using (Compiler.Local loc = ctx.GetLocalWithValue(expected, valueFrom))
            {
                // pre-callbacks
                EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.BeforeSerialize);

                Compiler.CodeLabel startFields = ctx.DefineLabel();
                // inheritance
                if (CanHaveInheritance)
                {
                    for (int i = 0; i < serializers.Length; i++)
                    {
                        IProtoSerializer ser     = serializers[i];
                        Type             serType = ser.ExpectedType;
                        if (serType != forType)
                        {
                            Compiler.CodeLabel ifMatch = ctx.DefineLabel(), nextTest = ctx.DefineLabel();
                            ctx.LoadValue(loc);
                            ctx.TryCast(serType);
                            ctx.CopyValue();
                            ctx.BranchIfTrue(ifMatch, true);
                            ctx.DiscardValue();
                            ctx.Branch(nextTest, true);
                            ctx.MarkLabel(ifMatch);
                            ser.EmitWrite(ctx, null);
                            ctx.Branch(startFields, false);
                            ctx.MarkLabel(nextTest);
                        }
                    }


                    if (constructType != null && constructType != forType)
                    {
                        using (Compiler.Local actualType = new Compiler.Local(ctx, ctx.MapType(typeof(System.Type))))
                        {
                            // would have jumped to "fields" if an expected sub-type, so two options:
                            // a: *exactly* that type, b: an *unexpected* type
                            ctx.LoadValue(loc);
                            ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType"));
                            ctx.CopyValue();
                            ctx.StoreValue(actualType);
                            ctx.LoadValue(forType);
                            ctx.BranchIfEqual(startFields, true);

                            ctx.LoadValue(actualType);
                            ctx.LoadValue(constructType);
                            ctx.BranchIfEqual(startFields, true);
                        }
                    }
                    else
                    {
                        // would have jumped to "fields" if an expected sub-type, so two options:
                        // a: *exactly* that type, b: an *unexpected* type
                        ctx.LoadValue(loc);
                        ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType"));
                        ctx.LoadValue(forType);
                        ctx.BranchIfEqual(startFields, true);
                    }
                    // unexpected, then... note that this *might* be a proxy, which
                    // is handled by ThrowUnexpectedSubtype
                    ctx.LoadValue(forType);
                    ctx.LoadValue(loc);
                    ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType"));
                    ctx.EmitCall(ctx.MapType(typeof(TypeModel)).GetMethod("ThrowUnexpectedSubtype",
                                                                          BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static));
                }
                // fields

                ctx.MarkLabel(startFields);
                for (int i = 0; i < serializers.Length; i++)
                {
                    IProtoSerializer ser = serializers[i];
                    if (ser.ExpectedType == forType)
                    {
                        ser.EmitWrite(ctx, loc);
                    }
                }

                // extension data
                if (isExtensible)
                {
                    ctx.LoadValue(loc);
                    ctx.LoadReaderWriter();
                    ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("AppendExtensionData"));
                }
                // post-callbacks
                EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.AfterSerialize);
            }
        }
 internal void WriteNullCheckedTail(Type type, IProtoSerializer tail, Compiler.Local valueFrom)
 {
     if (type.IsValueType)
     {
         Type underlyingType = null;
     #if !FX11
         underlyingType = Helpers.GetUnderlyingType(type);
     #endif
         if (underlyingType == null)
         { // not a nullable T; can invoke directly
             tail.EmitWrite(this, valueFrom);
         }
         else
         { // nullable T; check HasValue
             using (Compiler.Local valOrNull = GetLocalWithValue(type, valueFrom))
             {
                 LoadAddress(valOrNull, type);
                 LoadValue(type.GetProperty("HasValue"));
                 CodeLabel @end = DefineLabel();
                 BranchIfFalse(@end, false);
                 LoadAddress(valOrNull, type);
                 EmitCall(type.GetMethod("GetValueOrDefault", Helpers.EmptyTypes));
                 tail.EmitWrite(this, null);
                 MarkLabel(@end);
             }
         }
     }
     else
     { // ref-type; do a null-check
         LoadValue(valueFrom);
         CopyValue();
         CodeLabel hasVal = DefineLabel(), @end = DefineLabel();
         BranchIfTrue(hasVal, true);
         DiscardValue();
         Branch(@end, false);
         MarkLabel(hasVal);
         tail.EmitWrite(this, null);
         MarkLabel(@end);
     }
 }
Exemple #4
0
        void IProtoSerializer.EmitWrite(CompilerContext ctx, Local valueFrom)
        {
            Type expectedType = this.ExpectedType;

            using (Local local = ctx.GetLocalWithValue(expectedType, valueFrom))
            {
                this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.BeforeSerialize);
                CodeLabel label = ctx.DefineLabel();
                if (!this.CanHaveInheritance)
                {
                    goto Label_0206;
                }
                for (int i = 0; i < this.serializers.Length; i++)
                {
                    IProtoSerializer serializer = this.serializers[i];
                    Type             type       = serializer.ExpectedType;
                    if (type != this.forType)
                    {
                        CodeLabel label2 = ctx.DefineLabel();
                        CodeLabel label3 = ctx.DefineLabel();
                        ctx.LoadValue(local);
                        ctx.TryCast(type);
                        ctx.CopyValue();
                        ctx.BranchIfTrue(label2, true);
                        ctx.DiscardValue();
                        ctx.Branch(label3, true);
                        ctx.MarkLabel(label2);
                        serializer.EmitWrite(ctx, null);
                        ctx.Branch(label, false);
                        ctx.MarkLabel(label3);
                    }
                }
                if ((this.constructType != null) && (this.constructType != this.forType))
                {
                    using (Local local2 = new Local(ctx, ctx.MapType(typeof(Type))))
                    {
                        ctx.LoadValue(local);
                        ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType"));
                        ctx.CopyValue();
                        ctx.StoreValue(local2);
                        ctx.LoadValue(this.forType);
                        ctx.BranchIfEqual(label, true);
                        ctx.LoadValue(local2);
                        ctx.LoadValue(this.constructType);
                        ctx.BranchIfEqual(label, true);
                        goto Label_01B1;
                    }
                }
                ctx.LoadValue(local);
                ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType"));
                ctx.LoadValue(this.forType);
                ctx.BranchIfEqual(label, true);
Label_01B1:
                ctx.LoadValue(this.forType);
                ctx.LoadValue(local);
                ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType"));
                ctx.EmitCall(ctx.MapType(typeof(TypeModel)).GetMethod("ThrowUnexpectedSubtype", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static));
Label_0206:
                ctx.MarkLabel(label);
                for (int j = 0; j < this.serializers.Length; j++)
                {
                    IProtoSerializer serializer2 = this.serializers[j];
                    if (serializer2.ExpectedType == this.forType)
                    {
                        serializer2.EmitWrite(ctx, local);
                    }
                }
                if (this.isExtensible)
                {
                    ctx.LoadValue(local);
                    ctx.LoadReaderWriter();
                    ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("AppendExtensionData"));
                }
                this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.AfterSerialize);
            }
        }
Exemple #5
0
 void ProtoBuf.Serializers.IProtoSerializer.EmitWrite(CompilerContext ctx, Local valueFrom)
 {
     using (Local localWithValue = ctx.GetLocalWithValue(this.ExpectedType, valueFrom))
     {
         this.EmitCallbackIfNeeded(ctx, localWithValue, TypeModel.CallbackType.BeforeSerialize);
         CodeLabel codeLabel = ctx.DefineLabel();
         if (this.CanHaveInheritance)
         {
             for (int i = 0; i < (int)this.serializers.Length; i++)
             {
                 IProtoSerializer protoSerializer = this.serializers[i];
                 Type             expectedType    = protoSerializer.ExpectedType;
                 if (expectedType != this.forType)
                 {
                     CodeLabel codeLabel1 = ctx.DefineLabel();
                     CodeLabel codeLabel2 = ctx.DefineLabel();
                     ctx.LoadValue(localWithValue);
                     ctx.TryCast(expectedType);
                     ctx.CopyValue();
                     ctx.BranchIfTrue(codeLabel1, true);
                     ctx.DiscardValue();
                     ctx.Branch(codeLabel2, true);
                     ctx.MarkLabel(codeLabel1);
                     protoSerializer.EmitWrite(ctx, null);
                     ctx.Branch(codeLabel, false);
                     ctx.MarkLabel(codeLabel2);
                 }
             }
             if (this.constructType == null || this.constructType == this.forType)
             {
                 ctx.LoadValue(localWithValue);
                 ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType"));
                 ctx.LoadValue(this.forType);
                 ctx.BranchIfEqual(codeLabel, true);
             }
             else
             {
                 using (Local local = new Local(ctx, ctx.MapType(typeof(Type))))
                 {
                     ctx.LoadValue(localWithValue);
                     ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType"));
                     ctx.CopyValue();
                     ctx.StoreValue(local);
                     ctx.LoadValue(this.forType);
                     ctx.BranchIfEqual(codeLabel, true);
                     ctx.LoadValue(local);
                     ctx.LoadValue(this.constructType);
                     ctx.BranchIfEqual(codeLabel, true);
                 }
             }
             ctx.LoadValue(this.forType);
             ctx.LoadValue(localWithValue);
             ctx.EmitCall(ctx.MapType(typeof(object)).GetMethod("GetType"));
             ctx.EmitCall(ctx.MapType(typeof(TypeModel)).GetMethod("ThrowUnexpectedSubtype", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
         }
         ctx.MarkLabel(codeLabel);
         for (int j = 0; j < (int)this.serializers.Length; j++)
         {
             IProtoSerializer protoSerializer1 = this.serializers[j];
             if (protoSerializer1.ExpectedType == this.forType)
             {
                 protoSerializer1.EmitWrite(ctx, localWithValue);
             }
         }
         if (this.isExtensible)
         {
             ctx.LoadValue(localWithValue);
             ctx.LoadReaderWriter();
             ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("AppendExtensionData"));
         }
         this.EmitCallbackIfNeeded(ctx, localWithValue, TypeModel.CallbackType.AfterSerialize);
     }
 }