Esempio n. 1
0
        protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom)
        {
            // int i and T[] arr
            using (Compiler.Local arr = ctx.GetLocalWithValue(ExpectedType, valueFrom))
                using (Compiler.Local i = new ProtoBuf.Compiler.Local(ctx, typeof(int)))
                {
                    bool writePacked       = (options & OPTIONS_WritePacked) != 0;
                    bool fixedLengthPacked = writePacked && CanUsePackedPrefix();

                    using (Compiler.Local token = (writePacked && !fixedLengthPacked) ? new Compiler.Local(ctx, typeof(SubItemToken)) : null)
                    {
                        Type mappedWriter = typeof(ProtoWriter);
                        if (writePacked)
                        {
                            ctx.LoadValue(fieldNumber);
                            ctx.LoadValue((int)WireType.String);
                            ctx.LoadWriter(true);
                            ctx.EmitCall(ProtoWriter.GetStaticMethod("WriteFieldHeader"));

                            if (fixedLengthPacked)
                            {
                                // write directly - no need for buffering
                                ctx.LoadLength(arr, false);
                                ctx.LoadValue((int)packedWireType);
                                ctx.LoadWriter(true);
                                ctx.EmitCall(ProtoWriter.GetStaticMethod("WritePackedPrefix"));
                            }
                            else
                            {
                                ctx.LoadValue(arr);
                                ctx.LoadWriter(true);
                                ctx.EmitCall(ProtoWriter.GetStaticMethod("StartSubItem"));
                                ctx.StoreValue(token);
                            }
                            ctx.LoadValue(fieldNumber);
                            ctx.LoadWriter(false);
                            ctx.EmitCall(mappedWriter.GetMethod("SetPackedField"));
                        }
                        EmitWriteArrayLoop(ctx, i, arr);

                        if (writePacked)
                        {
                            if (fixedLengthPacked)
                            {
                                ctx.LoadValue(fieldNumber);
                                ctx.LoadWriter(false);
                                ctx.EmitCall(mappedWriter.GetMethod("ClearPackedField"));
                            }
                            else
                            {
                                ctx.LoadValue(token);
                                ctx.LoadWriter(true);
                                ctx.EmitCall(ProtoWriter.GetStaticMethod("EndSubItem"));
                            }
                        }
                    }
                }
        }
Esempio n. 2
0
        protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom)
        {
            using (Compiler.Local list = ctx.GetLocalWithValue(ExpectedType, valueFrom))
            {
                MethodInfo getEnumerator = GetEnumeratorInfo(out MethodInfo moveNext, out MethodInfo 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, typeof(SubItemToken)) : null)
                           {
                               if (writePacked)
                               {
                                   ctx.LoadValue(fieldNumber);
                                   ctx.LoadValue((int)WireType.String);
                                   ctx.LoadWriter(true);
                                   ctx.EmitCall(ProtoWriter.GetStaticMethod("WriteFieldHeader"));

                                   ctx.LoadValue(list);
                                   ctx.LoadWriter(true);
                                   ctx.EmitCall(ProtoWriter.GetStaticMethod("StartSubItem"));
                                   ctx.StoreValue(token);

                                   ctx.LoadValue(fieldNumber);
                                   ctx.LoadWriter(false);
                                   ctx.EmitCall(typeof(ProtoWriter).GetMethod("SetPackedField"));
                               }

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

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

                               if (writePacked)
                               {
                                   ctx.LoadValue(token);
                                   ctx.LoadWriter(true);
                                   ctx.EmitCall(ProtoWriter.GetStaticMethod("EndSubItem"));
                               }
                           }
            }
        }