public override void EmitReadRoot(CompilerContext context, Local valueFrom)
        {   // => (T)((IProtoSubTypeSerializer<TBase>)this).ReadSubType(reader, ref state, SubTypeState<TBase>.Create<T>(state.Context, value));
            // or
            // => state.ReadBaseType<TBase, T>(value, this);
            if (context.IsService)
            {
                using var tmp = context.GetLocalWithValue(typeof(T), valueFrom);
                context.LoadSelfAsService <ISubTypeSerializer <TBase>, TBase>();
                context.LoadState();

                // sub-state
                context.LoadSerializationContext(typeof(ISerializationContext));
                context.LoadValue(tmp);
                context.EmitCall(typeof(SubTypeState <TBase>)
                                 .GetMethod(nameof(SubTypeState <string> .Create), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(typeof(T)));
                context.EmitCall(typeof(ISubTypeSerializer <TBase>)
                                 .GetMethod(nameof(ISubTypeSerializer <string> .ReadSubType), BindingFlags.Public | BindingFlags.Instance));
                if (typeof(T) != typeof(TBase))
                {
                    context.Cast(typeof(T));
                }
            }
            else
            {
                context.LoadState();
                context.LoadValue(valueFrom);
                context.LoadSelfAsService <ISubTypeSerializer <TBase>, TBase>();
                context.EmitCall(typeof(ProtoReader.State).GetMethod(nameof(ProtoReader.State.ReadBaseType), BindingFlags.Public | BindingFlags.Instance)
                                 .MakeGenericMethod(typeof(TBase), typeof(T)));
            }
        }
Exemple #2
0
        private void WriteFieldHandler(CompilerContext ctx, Type expected, Local loc, CodeLabel handler, CodeLabel @continue, IProtoSerializer serializer)
        {
            ctx.MarkLabel(handler);
            Type expectedType = serializer.ExpectedType;

            if (expectedType == this.forType)
            {
                this.EmitCreateIfNull(ctx, loc);
                serializer.EmitRead(ctx, loc);
            }
            else
            {
                RuntimeTypeModel model = (RuntimeTypeModel)ctx.Model;
                if (((IProtoTypeSerializer)serializer).CanCreateInstance())
                {
                    CodeLabel label = ctx.DefineLabel();
                    ctx.LoadValue(loc);
                    ctx.BranchIfFalse(label, false);
                    ctx.LoadValue(loc);
                    ctx.TryCast(expectedType);
                    ctx.BranchIfTrue(label, false);
                    ctx.LoadReaderWriter();
                    ctx.LoadValue(loc);
                    ((IProtoTypeSerializer)serializer).EmitCreateInstance(ctx);
                    ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("Merge"));
                    ctx.Cast(expected);
                    ctx.StoreValue(loc);
                    ctx.MarkLabel(label);
                }
                ctx.LoadValue(loc);
                ctx.Cast(expectedType);
                serializer.EmitRead(ctx, null);
            }
            if (serializer.ReturnsValue)
            {
                ctx.StoreValue(loc);
            }
            ctx.Branch(@continue, false);
        }
Exemple #3
0
        void IProtoTypeSerializer.EmitCreateInstance(CompilerContext ctx)
        {
            bool flag = true;

            if (this.factory != null)
            {
                EmitInvokeCallback(ctx, this.factory, false, this.constructType, this.forType);
            }
            else if (!this.useConstructor)
            {
                ctx.LoadValue(this.constructType);
                ctx.EmitCall(ctx.MapType(typeof(BclHelpers)).GetMethod("GetUninitializedObject"));
                ctx.Cast(this.forType);
            }
            else if (this.constructType.IsClass && this.hasConstructor)
            {
                ctx.EmitCtor(this.constructType);
            }
            else
            {
                ctx.LoadValue(this.ExpectedType);
                ctx.EmitCall(ctx.MapType(typeof(TypeModel)).GetMethod("ThrowCannotCreateInstance", BindingFlags.Public | BindingFlags.Static));
                ctx.LoadNullRef();
                flag = false;
            }
            if (flag)
            {
                ctx.CopyValue();
                ctx.LoadReaderWriter();
                ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("NoteObject", BindingFlags.Public | BindingFlags.Static));
            }
            if (this.baseCtorCallbacks != null)
            {
                for (int i = 0; i < this.baseCtorCallbacks.Length; i++)
                {
                    EmitInvokeCallback(ctx, this.baseCtorCallbacks[i], true, null, this.forType);
                }
            }
        }
Exemple #4
0
        private bool EmitDedicatedMethod(CompilerContext ctx, Local valueFrom, bool read)
        {
            MethodBuilder dedicatedMethod = ctx.GetDedicatedMethod(this.key, read);

            if (dedicatedMethod == null)
            {
                return(false);
            }
            using (Local local = new Local(ctx, ctx.MapType(typeof(SubItemToken))))
            {
                Type type = ctx.MapType((read ? typeof(ProtoReader) : typeof(ProtoWriter)));
                ctx.LoadValue(valueFrom);
                if (!read)
                {
                    if (this.type.IsValueType || !this.recursionCheck)
                    {
                        ctx.LoadNullRef();
                    }
                    else
                    {
                        ctx.CopyValue();
                    }
                }
                ctx.LoadReaderWriter();
                ctx.EmitCall(type.GetMethod("StartSubItem"));
                ctx.StoreValue(local);
                ctx.LoadReaderWriter();
                ctx.EmitCall(dedicatedMethod);
                if (read && this.type != dedicatedMethod.ReturnType)
                {
                    ctx.Cast(this.type);
                }
                ctx.LoadValue(local);
                ctx.LoadReaderWriter();
                ctx.EmitCall(type.GetMethod("EndSubItem"));
            }
            return(true);
        }
Exemple #5
0
        private static void EmitReadAndAddItem(CompilerContext ctx, Local list, IProtoSerializer tail, MethodInfo add, bool castListForAdd)
        {
            ctx.LoadAddress(list, list.Type);
            if (castListForAdd)
            {
                ctx.Cast(add.DeclaringType);
            }
            Type expectedType = tail.ExpectedType;
            bool returnsValue = tail.ReturnsValue;

            if (!tail.RequiresOldValue)
            {
                if (!returnsValue)
                {
                    throw new InvalidOperationException();
                }
                tail.EmitRead(ctx, null);
            }
            else if (expectedType.IsValueType || !returnsValue)
            {
                using (Local local = new Local(ctx, expectedType))
                {
                    if (!expectedType.IsValueType)
                    {
                        ctx.LoadNullRef();
                        ctx.StoreValue(local);
                    }
                    else
                    {
                        ctx.LoadAddress(local, expectedType);
                        ctx.EmitCtor(expectedType);
                    }
                    tail.EmitRead(ctx, local);
                    if (!returnsValue)
                    {
                        ctx.LoadValue(local);
                    }
                }
            }
            else
            {
                ctx.LoadNullRef();
                tail.EmitRead(ctx, null);
            }
            Type parameterType = add.GetParameters()[0].ParameterType;

            if (parameterType != expectedType)
            {
                if (parameterType != ctx.MapType(typeof(object)))
                {
                    if (Helpers.GetUnderlyingType(parameterType) != expectedType)
                    {
                        throw new InvalidOperationException("Conflicting item/add type");
                    }
                    Type[] typeArray = new Type[] { expectedType };
                    ctx.EmitCtor(Helpers.GetConstructor(parameterType, typeArray, false));
                }
                else
                {
                    ctx.CastToObject(expectedType);
                }
            }
            ctx.EmitCall(add);
            if (add.ReturnType != ctx.MapType(typeof(void)))
            {
                ctx.DiscardValue();
            }
        }
Exemple #6
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);
                    }
                }
            }
        }
        protected override void EmitRead(CompilerContext ctx, Local valueFrom)
        {
            MethodInfo methodInfo;
            MethodInfo methodInfo1;
            Local      localWithValue;

            if (base.AppendToCollection)
            {
                localWithValue = ctx.GetLocalWithValue(this.ExpectedType, valueFrom);
            }
            else
            {
                localWithValue = null;
            }
            using (Local local = localWithValue)
            {
                using (Local local1 = new Local(ctx, this.builderFactory.ReturnType))
                {
                    ctx.EmitCall(this.builderFactory);
                    ctx.StoreValue(local1);
                    if (base.AppendToCollection)
                    {
                        CodeLabel codeLabel = ctx.DefineLabel();
                        if (!this.ExpectedType.IsValueType)
                        {
                            ctx.LoadValue(local);
                            ctx.BranchIfFalse(codeLabel, false);
                        }
                        PropertyInfo property = Helpers.GetProperty(this.ExpectedType, "Length", false) ?? Helpers.GetProperty(this.ExpectedType, "Count", false) ?? Helpers.GetProperty(ImmutableCollectionDecorator.ResolveIReadOnlyCollection(this.ExpectedType, this.Tail.ExpectedType), "Count", false);
                        ctx.LoadAddress(local, local.Type);
                        ctx.EmitCall(Helpers.GetGetMethod(property, false, false));
                        ctx.BranchIfFalse(codeLabel, false);
                        Type type = ctx.MapType(typeof(void));
                        if (this.addRange == null)
                        {
                            MethodInfo enumeratorInfo = base.GetEnumeratorInfo(ctx.Model, out methodInfo, out methodInfo1);
                            Type       returnType     = enumeratorInfo.ReturnType;
                            using (Local local2 = new Local(ctx, returnType))
                            {
                                ctx.LoadAddress(local, this.ExpectedType);
                                ctx.EmitCall(enumeratorInfo);
                                ctx.StoreValue(local2);
                                using (IDisposable disposable = ctx.Using(local2))
                                {
                                    CodeLabel codeLabel1 = ctx.DefineLabel();
                                    CodeLabel codeLabel2 = ctx.DefineLabel();
                                    ctx.Branch(codeLabel2, false);
                                    ctx.MarkLabel(codeLabel1);
                                    ctx.LoadAddress(local1, local1.Type);
                                    ctx.LoadAddress(local2, returnType);
                                    ctx.EmitCall(methodInfo1);
                                    ctx.EmitCall(this.@add);
                                    if ([email protected] != null && [email protected] != type)
                                    {
                                        ctx.DiscardValue();
                                    }
                                    ctx.MarkLabel(codeLabel2);
                                    ctx.LoadAddress(local2, returnType);
                                    ctx.EmitCall(methodInfo);
                                    ctx.BranchIfTrue(codeLabel1, false);
                                }
                            }
                        }
                        else
                        {
                            ctx.LoadValue(local1);
                            ctx.LoadValue(local);
                            ctx.EmitCall(this.addRange);
                            if (this.addRange.ReturnType != null && [email protected] != type)
                            {
                                ctx.DiscardValue();
                            }
                        }
                        ctx.MarkLabel(codeLabel);
                    }
                    ListDecorator.EmitReadList(ctx, local1, this.Tail, this.@add, this.packedWireType, false);
                    ctx.LoadAddress(local1, local1.Type);
                    ctx.EmitCall(this.finish);
                    if (this.ExpectedType != this.finish.ReturnType)
                    {
                        ctx.Cast(this.ExpectedType);
                    }
                }
            }
        }