示例#1
0
        protected override void EmitWrite(CompilerContext ctx, Local valueFrom)
        {
            Type       itemType = typeof(KeyValuePair <TKey, TValue>);
            MethodInfo moveNext, current, getEnumerator = ListDecorator.GetEnumeratorInfo(ctx.Model,
                                                                                          ExpectedType, itemType, out moveNext, out current);
            Type enumeratorType = getEnumerator.ReturnType;

            MethodInfo key    = itemType.GetProperty(nameof(KeyValuePair <TKey, TValue> .Key)).GetGetMethod(),
                       @value = itemType.GetProperty(nameof(KeyValuePair <TKey, TValue> .Value)).GetGetMethod();

            using (Compiler.Local list = ctx.GetLocalWithValue(ExpectedType, valueFrom))
                using (Compiler.Local iter = new Compiler.Local(ctx, enumeratorType))
                    using (Compiler.Local token = new Compiler.Local(ctx, typeof(SubItemToken)))
                        using (Compiler.Local kvp = new Compiler.Local(ctx, itemType))
                        {
                            ctx.LoadAddress(list, ExpectedType);
                            ctx.EmitCall(getEnumerator, ExpectedType);
                            ctx.StoreValue(iter);
                            using (ctx.Using(iter))
                            {
                                Compiler.CodeLabel body = ctx.DefineLabel(), next = ctx.DefineLabel();
                                ctx.Branch(next, false);

                                ctx.MarkLabel(body);

                                ctx.LoadAddress(iter, enumeratorType);
                                ctx.EmitCall(current, enumeratorType);

                                if (itemType != ctx.MapType(typeof(object)) && current.ReturnType == ctx.MapType(typeof(object)))
                                {
                                    ctx.CastFromObject(itemType);
                                }
                                ctx.StoreValue(kvp);

                                ctx.LoadValue(fieldNumber);
                                ctx.LoadValue((int)wireType);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("WriteFieldHeader"));

                                ctx.LoadNullRef();
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("StartSubItem"));
                                ctx.StoreValue(token);

                                ctx.LoadAddress(kvp, itemType);
                                ctx.EmitCall(key, itemType);
                                ctx.WriteNullCheckedTail(typeof(TKey), keyTail, null);

                                ctx.LoadAddress(kvp, itemType);
                                ctx.EmitCall(value, itemType);
                                ctx.WriteNullCheckedTail(typeof(TValue), Tail, null);

                                ctx.LoadValue(token);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("EndSubItem"));

                                ctx.MarkLabel(@next);
                                ctx.LoadAddress(iter, enumeratorType);
                                ctx.EmitCall(moveNext, enumeratorType);
                                ctx.BranchIfTrue(body, false);
                            }
                        }
        }
示例#2
0
        protected override void EmitRead(CompilerContext ctx, Local valueFrom)
        {
            using (Compiler.Local list = AppendToCollection ? ctx.GetLocalWithValue(ExpectedType, valueFrom)
                : new Compiler.Local(ctx, typeof(TDictionary)))
                using (Compiler.Local token = new Compiler.Local(ctx, typeof(SubItemToken)))
                    using (Compiler.Local key = new Compiler.Local(ctx, typeof(TKey)))
                        using (Compiler.Local @value = new Compiler.Local(ctx, typeof(TValue)))
                            using (Compiler.Local fieldNumber = new Compiler.Local(ctx, ctx.MapType(typeof(int))))
                            {
                                if (!AppendToCollection)
                                { // always new
                                    ctx.LoadNullRef();
                                    ctx.StoreValue(list);
                                }
                                if (concreteType != null)
                                {
                                    ctx.LoadValue(list);
                                    Compiler.CodeLabel notNull = ctx.DefineLabel();
                                    ctx.BranchIfTrue(notNull, true);
                                    ctx.EmitCtor(concreteType);
                                    ctx.StoreValue(list);
                                    ctx.MarkLabel(notNull);
                                }

                                var redoFromStart = ctx.DefineLabel();
                                ctx.MarkLabel(redoFromStart);

                                // key = default(TKey); value = default(TValue);
                                if (typeof(TKey) == typeof(string))
                                {
                                    ctx.LoadValue("");
                                    ctx.StoreValue(key);
                                }
                                else
                                {
                                    ctx.InitLocal(typeof(TKey), key);
                                }
                                if (typeof(TValue) == typeof(string))
                                {
                                    ctx.LoadValue("");
                                    ctx.StoreValue(value);
                                }
                                else
                                {
                                    ctx.InitLocal(typeof(TValue), @value);
                                }

                                // token = ProtoReader.StartSubItem(reader);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("StartSubItem"));
                                ctx.StoreValue(token);

                                Compiler.CodeLabel @continue = ctx.DefineLabel(), processField = ctx.DefineLabel();
                                // while ...
                                ctx.Branch(@continue, false);

                                // switch(fieldNumber)
                                ctx.MarkLabel(processField);
                                ctx.LoadValue(fieldNumber);
                                CodeLabel @default = ctx.DefineLabel(), one = ctx.DefineLabel(), two = ctx.DefineLabel();
                                ctx.Switch(new[] { @default, one, two }); // zero based, hence explicit 0

                                // case 0: default: reader.SkipField();
                                ctx.MarkLabel(@default);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField"));
                                ctx.Branch(@continue, false);

                                // case 1: key = ...
                                ctx.MarkLabel(one);
                                keyTail.EmitRead(ctx, null);
                                ctx.StoreValue(key);
                                ctx.Branch(@continue, false);

                                // case 2: value = ...
                                ctx.MarkLabel(two);
                                Tail.EmitRead(ctx, Tail.RequiresOldValue ? @value : null);
                                ctx.StoreValue(value);

                                // (fieldNumber = reader.ReadFieldHeader()) > 0
                                ctx.MarkLabel(@continue);
                                ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int)));
                                ctx.CopyValue();
                                ctx.StoreValue(fieldNumber);
                                ctx.LoadValue(0);
                                ctx.BranchIfGreater(processField, false);

                                // ProtoReader.EndSubItem(token, reader);
                                ctx.LoadValue(token);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("EndSubItem"));

                                // list[key] = value;
                                ctx.LoadAddress(list, ExpectedType);
                                ctx.LoadValue(key);
                                ctx.LoadValue(@value);
                                ctx.EmitCall(indexerSet);

                                // while reader.TryReadFieldReader(fieldNumber)
                                ctx.LoadReaderWriter();
                                ctx.LoadValue(this.fieldNumber);
                                ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("TryReadFieldHeader"));
                                ctx.BranchIfTrue(redoFromStart, false);

                                if (ReturnsValue)
                                {
                                    ctx.LoadValue(list);
                                }
                            }
        }
示例#3
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);
     }
 }
示例#4
0
        void ProtoBuf.Serializers.IProtoSerializer.EmitRead(CompilerContext ctx, Local valueFrom)
        {
            Type expectedType = this.ExpectedType;

            using (Local localWithValue = ctx.GetLocalWithValue(expectedType, valueFrom))
            {
                using (Local local = new Local(ctx, ctx.MapType(typeof(int))))
                {
                    if (this.HasCallbacks(TypeModel.CallbackType.BeforeDeserialize))
                    {
                        if (!this.ExpectedType.IsValueType)
                        {
                            CodeLabel codeLabel = ctx.DefineLabel();
                            ctx.LoadValue(localWithValue);
                            ctx.BranchIfFalse(codeLabel, false);
                            this.EmitCallbackIfNeeded(ctx, localWithValue, TypeModel.CallbackType.BeforeDeserialize);
                            ctx.MarkLabel(codeLabel);
                        }
                        else
                        {
                            this.EmitCallbackIfNeeded(ctx, localWithValue, TypeModel.CallbackType.BeforeDeserialize);
                        }
                    }
                    CodeLabel codeLabel1 = ctx.DefineLabel();
                    CodeLabel codeLabel2 = ctx.DefineLabel();
                    ctx.Branch(codeLabel1, false);
                    ctx.MarkLabel(codeLabel2);
                    BasicList.NodeEnumerator enumerator = BasicList.GetContiguousGroups(this.fieldNumbers, this.serializers).GetEnumerator();
                    while (enumerator.MoveNext())
                    {
                        BasicList.Group current    = (BasicList.Group)enumerator.Current;
                        CodeLabel       codeLabel3 = ctx.DefineLabel();
                        int             count      = current.Items.Count;
                        if (count != 1)
                        {
                            ctx.LoadValue(local);
                            ctx.LoadValue(current.First);
                            ctx.Subtract();
                            CodeLabel[] codeLabelArray = new CodeLabel[count];
                            for (int i = 0; i < count; i++)
                            {
                                codeLabelArray[i] = ctx.DefineLabel();
                            }
                            ctx.Switch(codeLabelArray);
                            ctx.Branch(codeLabel3, false);
                            for (int j = 0; j < count; j++)
                            {
                                this.WriteFieldHandler(ctx, expectedType, localWithValue, codeLabelArray[j], codeLabel1, (IProtoSerializer)current.Items[j]);
                            }
                        }
                        else
                        {
                            ctx.LoadValue(local);
                            ctx.LoadValue(current.First);
                            CodeLabel codeLabel4 = ctx.DefineLabel();
                            ctx.BranchIfEqual(codeLabel4, true);
                            ctx.Branch(codeLabel3, false);
                            this.WriteFieldHandler(ctx, expectedType, localWithValue, codeLabel4, codeLabel1, (IProtoSerializer)current.Items[0]);
                        }
                        ctx.MarkLabel(codeLabel3);
                    }
                    this.EmitCreateIfNull(ctx, localWithValue);
                    ctx.LoadReaderWriter();
                    if (!this.isExtensible)
                    {
                        ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField"));
                    }
                    else
                    {
                        ctx.LoadValue(localWithValue);
                        ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("AppendExtensionData"));
                    }
                    ctx.MarkLabel(codeLabel1);
                    ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int)));
                    ctx.CopyValue();
                    ctx.StoreValue(local);
                    ctx.LoadValue(0);
                    ctx.BranchIfGreater(codeLabel2, false);
                    this.EmitCreateIfNull(ctx, localWithValue);
                    this.EmitCallbackIfNeeded(ctx, localWithValue, TypeModel.CallbackType.AfterDeserialize);
                    if (valueFrom != null && !localWithValue.IsSame(valueFrom))
                    {
                        ctx.LoadValue(localWithValue);
                        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);
                    }
                }
            }
        }
        public void EmitRead(CompilerContext ctx, Local incoming)
        {
            Local local;

            using (Local localWithValue = ctx.GetLocalWithValue(this.ExpectedType, incoming))
            {
                Local[] localArray = new Local[(int)this.members.Length];
                try
                {
                    for (int i = 0; i < (int)localArray.Length; i++)
                    {
                        Type memberType = this.GetMemberType(i);
                        bool flag       = true;
                        localArray[i] = new Local(ctx, memberType);
                        if (!this.ExpectedType.IsValueType)
                        {
                            if (!memberType.IsValueType)
                            {
                                ctx.LoadNullRef();
                            }
                            else
                            {
                                ProtoTypeCode typeCode = Helpers.GetTypeCode(memberType);
                                switch (typeCode)
                                {
                                case ProtoTypeCode.Boolean:
                                case ProtoTypeCode.SByte:
                                case ProtoTypeCode.Byte:
                                case ProtoTypeCode.Int16:
                                case ProtoTypeCode.UInt16:
                                case ProtoTypeCode.Int32:
                                case ProtoTypeCode.UInt32:
                                {
                                    ctx.LoadValue(0);
                                    break;
                                }

                                case ProtoTypeCode.Char:
                                {
                                    ctx.LoadAddress(localArray[i], memberType);
                                    ctx.EmitCtor(memberType);
                                    flag = false;
                                    break;
                                }

                                case ProtoTypeCode.Int64:
                                case ProtoTypeCode.UInt64:
                                {
                                    ctx.LoadValue((long)0);
                                    break;
                                }

                                case ProtoTypeCode.Single:
                                {
                                    ctx.LoadValue(0f);
                                    break;
                                }

                                case ProtoTypeCode.Double:
                                {
                                    ctx.LoadValue(0);
                                    break;
                                }

                                case ProtoTypeCode.Decimal:
                                {
                                    ctx.LoadValue(new decimal(0));
                                    break;
                                }

                                default:
                                {
                                    if (typeCode == ProtoTypeCode.Guid)
                                    {
                                        ctx.LoadValue(Guid.Empty);
                                        break;
                                    }
                                    else
                                    {
                                        goto case ProtoTypeCode.Char;
                                    }
                                }
                                }
                            }
                            if (flag)
                            {
                                ctx.StoreValue(localArray[i]);
                            }
                        }
                    }
                    CodeLabel codeLabel = (this.ExpectedType.IsValueType ? new CodeLabel() : ctx.DefineLabel());
                    if (!this.ExpectedType.IsValueType)
                    {
                        ctx.LoadAddress(localWithValue, this.ExpectedType);
                        ctx.BranchIfFalse(codeLabel, false);
                    }
                    for (int j = 0; j < (int)this.members.Length; j++)
                    {
                        ctx.LoadAddress(localWithValue, this.ExpectedType);
                        MemberTypes memberType1 = this.members[j].MemberType;
                        if (memberType1 == MemberTypes.Field)
                        {
                            ctx.LoadValue((FieldInfo)this.members[j]);
                        }
                        else if (memberType1 == MemberTypes.Property)
                        {
                            ctx.LoadValue((PropertyInfo)this.members[j]);
                        }
                        ctx.StoreValue(localArray[j]);
                    }
                    if (!this.ExpectedType.IsValueType)
                    {
                        ctx.MarkLabel(codeLabel);
                    }
                    using (Local local1 = new Local(ctx, ctx.MapType(typeof(int))))
                    {
                        CodeLabel codeLabel1 = ctx.DefineLabel();
                        CodeLabel codeLabel2 = ctx.DefineLabel();
                        CodeLabel codeLabel3 = ctx.DefineLabel();
                        ctx.Branch(codeLabel1, false);
                        CodeLabel[] codeLabelArray = new CodeLabel[(int)this.members.Length];
                        for (int k = 0; k < (int)this.members.Length; k++)
                        {
                            codeLabelArray[k] = ctx.DefineLabel();
                        }
                        ctx.MarkLabel(codeLabel2);
                        ctx.LoadValue(local1);
                        ctx.LoadValue(1);
                        ctx.Subtract();
                        ctx.Switch(codeLabelArray);
                        ctx.Branch(codeLabel3, false);
                        for (int l = 0; l < (int)codeLabelArray.Length; l++)
                        {
                            ctx.MarkLabel(codeLabelArray[l]);
                            IProtoSerializer protoSerializer = this.tails[l];
                            if (protoSerializer.RequiresOldValue)
                            {
                                local = localArray[l];
                            }
                            else
                            {
                                local = null;
                            }
                            ctx.ReadNullCheckedTail(localArray[l].Type, protoSerializer, local);
                            if (protoSerializer.ReturnsValue)
                            {
                                if (!localArray[l].Type.IsValueType)
                                {
                                    CodeLabel codeLabel4 = ctx.DefineLabel();
                                    CodeLabel codeLabel5 = ctx.DefineLabel();
                                    ctx.CopyValue();
                                    ctx.BranchIfTrue(codeLabel4, true);
                                    ctx.DiscardValue();
                                    ctx.Branch(codeLabel5, true);
                                    ctx.MarkLabel(codeLabel4);
                                    ctx.StoreValue(localArray[l]);
                                    ctx.MarkLabel(codeLabel5);
                                }
                                else
                                {
                                    ctx.StoreValue(localArray[l]);
                                }
                            }
                            ctx.Branch(codeLabel1, false);
                        }
                        ctx.MarkLabel(codeLabel3);
                        ctx.LoadReaderWriter();
                        ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField"));
                        ctx.MarkLabel(codeLabel1);
                        ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int)));
                        ctx.CopyValue();
                        ctx.StoreValue(local1);
                        ctx.LoadValue(0);
                        ctx.BranchIfGreater(codeLabel2, false);
                    }
                    for (int m = 0; m < (int)localArray.Length; m++)
                    {
                        ctx.LoadValue(localArray[m]);
                    }
                    ctx.EmitCtor(this.ctor);
                    ctx.StoreValue(localWithValue);
                }
                finally
                {
                    for (int n = 0; n < (int)localArray.Length; n++)
                    {
                        if (localArray[n] != null)
                        {
                            localArray[n].Dispose();
                        }
                    }
                }
            }
        }
示例#7
0
 void ProtoBuf.Serializers.IProtoSerializer.EmitRead(CompilerContext ctx, Local valueFrom)
 {
     ctx.EmitBasicRead("ReadString", ctx.MapType(typeof(string)));
     ctx.EmitCall(this.parse);
 }