예제 #1
0
 protected override void EmitRead(UcAsp.RPC.ProtoBuf.Compiler.CompilerContext ctx, UcAsp.RPC.ProtoBuf.Compiler.Local valueFrom)
 {
     if (strict || NeedsHint)
     {
         ctx.LoadReaderWriter();
         ctx.LoadValue((int)wireType);
         ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod(strict ? "Assert" : "Hint"));
     }
     Tail.EmitRead(ctx, valueFrom);
 }
예제 #2
0
        protected override void EmitWrite(UcAsp.RPC.ProtoBuf.Compiler.CompilerContext ctx, UcAsp.RPC.ProtoBuf.Compiler.Local valueFrom)
        {
            // int i and T[] arr
            using (Compiler.Local arr = ctx.GetLocalWithValue(arrayType, valueFrom))
                using (Compiler.Local i = new UcAsp.RPC.ProtoBuf.Compiler.Local(ctx, ctx.MapType(typeof(int))))
                {
                    bool writePacked       = (options & OPTIONS_WritePacked) != 0;
                    bool fixedLengthPacked = writePacked && CanUsePackedPrefix();

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

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

                        if (writePacked)
                        {
                            if (fixedLengthPacked)
                            {
                                ctx.LoadValue(fieldNumber);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(mappedWriter.GetMethod("ClearPackedField"));
                            }
                            else
                            {
                                ctx.LoadValue(token);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(mappedWriter.GetMethod("EndSubItem"));
                            }
                        }
                    }
                }
        }
예제 #3
0
        internal static void EmitReadList(UcAsp.RPC.ProtoBuf.Compiler.CompilerContext ctx, Compiler.Local list, IProtoSerializer tail, MethodInfo add, WireType packedWireType, bool castListForAdd)
        {
            using (Compiler.Local fieldNumber = new Compiler.Local(ctx, ctx.MapType(typeof(int))))
            {
                Compiler.CodeLabel readPacked = packedWireType == WireType.None ? new Compiler.CodeLabel() : ctx.DefineLabel();
                if (packedWireType != WireType.None)
                {
                    ctx.LoadReaderWriter();
                    ctx.LoadValue(typeof(ProtoReader).GetProperty("WireType"));
                    ctx.LoadValue((int)WireType.String);
                    ctx.BranchIfEqual(readPacked, false);
                }
                ctx.LoadReaderWriter();
                ctx.LoadValue(typeof(ProtoReader).GetProperty("FieldNumber"));
                ctx.StoreValue(fieldNumber);

                Compiler.CodeLabel @continue = ctx.DefineLabel();
                ctx.MarkLabel(@continue);

                EmitReadAndAddItem(ctx, list, tail, add, castListForAdd);

                ctx.LoadReaderWriter();
                ctx.LoadValue(fieldNumber);
                ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("TryReadFieldHeader"));
                ctx.BranchIfTrue(@continue, false);

                if (packedWireType != WireType.None)
                {
                    Compiler.CodeLabel allDone = ctx.DefineLabel();
                    ctx.Branch(allDone, false);
                    ctx.MarkLabel(readPacked);

                    ctx.LoadReaderWriter();
                    ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("StartSubItem"));

                    Compiler.CodeLabel testForData = ctx.DefineLabel(), noMoreData = ctx.DefineLabel();
                    ctx.MarkLabel(testForData);
                    ctx.LoadValue((int)packedWireType);
                    ctx.LoadReaderWriter();
                    ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("HasSubValue"));
                    ctx.BranchIfFalse(noMoreData, false);

                    EmitReadAndAddItem(ctx, list, tail, add, castListForAdd);
                    ctx.Branch(testForData, false);

                    ctx.MarkLabel(noMoreData);
                    ctx.LoadReaderWriter();
                    ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("EndSubItem"));
                    ctx.MarkLabel(allDone);
                }
            }
        }
예제 #4
0
        protected override void EmitWrite(UcAsp.RPC.ProtoBuf.Compiler.CompilerContext ctx, UcAsp.RPC.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, 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 != 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, enumeratorType);
                            ctx.BranchIfTrue(body, false);
                        }

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