Пример #1
0
        protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom)
        {
            using (Compiler.Local list = ctx.GetLocalWithValue(ExpectedType, valueFrom))
            {
                MethodInfo moveNext, current, getEnumerator = GetEnumeratorInfo(ctx.Model, out moveNext, out current);
                Helpers.DebugAssert(moveNext != null);
                Helpers.DebugAssert(current != null);
                Helpers.DebugAssert(getEnumerator != null);
                Type enumeratorType = getEnumerator.ReturnType;
                bool writePacked    = WritePacked;
                using (Compiler.Local iter = new Compiler.Local(ctx, enumeratorType))
                    using (Compiler.Local token = writePacked ? new Compiler.Local(ctx, ctx.MapType(typeof(SubItemToken))) : null)
                    {
                        if (writePacked)
                        {
                            ctx.LoadValue(fieldNumber);
                            ctx.LoadValue((int)WireType.String);
                            ctx.LoadReaderWriter();
                            ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("WriteFieldHeader"));

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

                            ctx.LoadValue(fieldNumber);
                            ctx.LoadReaderWriter();
                            ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("SetPackedField"));
                        }

                        ctx.LoadAddress(list, ExpectedType);
                        ctx.EmitCall(getEnumerator);
                        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);
                            Type itemType = Tail.ExpectedType;
                            if (itemType != ctx.MapType(typeof(object)) && current.ReturnType == ctx.MapType(typeof(object)))
                            {
                                ctx.CastFromObject(itemType);
                            }
                            Tail.EmitWrite(ctx, null);

                            ctx.MarkLabel(@next);
                            ctx.LoadAddress(iter, enumeratorType);
                            ctx.EmitCall(moveNext);
                            ctx.BranchIfTrue(body, false);
                        }

                        if (writePacked)
                        {
                            ctx.LoadValue(token);
                            ctx.LoadReaderWriter();
                            ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("EndSubItem"));
                        }
                    }
            }
        }