예제 #1
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"));
                            }
                        }
                    }
                }
        }
예제 #2
0
        protected override void EmitRead(UcAsp.RPC.ProtoBuf.Compiler.CompilerContext ctx, UcAsp.RPC.ProtoBuf.Compiler.Local valueFrom)
        {
            Type listType;

#if NO_GENERICS
            listType = typeof(BasicList);
#else
            listType = ctx.MapType(typeof(System.Collections.Generic.List <>)).MakeGenericType(itemType);
#endif
            Type expected = ExpectedType;
            using (Compiler.Local oldArr = AppendToCollection ? ctx.GetLocalWithValue(expected, valueFrom) : null)
                using (Compiler.Local newArr = new Compiler.Local(ctx, expected))
                    using (Compiler.Local list = new Compiler.Local(ctx, listType))
                    {
                        ctx.EmitCtor(listType);
                        ctx.StoreValue(list);
                        ListDecorator.EmitReadList(ctx, list, Tail, listType.GetMethod("Add"), packedWireType, false);

                        // leave this "using" here, as it can share the "FieldNumber" local with EmitReadList
                        using (Compiler.Local oldLen = AppendToCollection ? new UcAsp.RPC.ProtoBuf.Compiler.Local(ctx, ctx.MapType(typeof(int))) : null) {
                            Type[] copyToArrayInt32Args = new Type[] { ctx.MapType(typeof(Array)), ctx.MapType(typeof(int)) };

                            if (AppendToCollection)
                            {
                                ctx.LoadLength(oldArr, true);
                                ctx.CopyValue();
                                ctx.StoreValue(oldLen);

                                ctx.LoadAddress(list, listType);
                                ctx.LoadValue(listType.GetProperty("Count"));
                                ctx.Add();
                                ctx.CreateArray(itemType, null); // length is on the stack
                                ctx.StoreValue(newArr);

                                ctx.LoadValue(oldLen);
                                Compiler.CodeLabel nothingToCopy = ctx.DefineLabel();
                                ctx.BranchIfFalse(nothingToCopy, true);
                                ctx.LoadValue(oldArr);
                                ctx.LoadValue(newArr);
                                ctx.LoadValue(0); // index in target

                                ctx.EmitCall(expected.GetMethod("CopyTo", copyToArrayInt32Args));
                                ctx.MarkLabel(nothingToCopy);

                                ctx.LoadValue(list);
                                ctx.LoadValue(newArr);
                                ctx.LoadValue(oldLen);
                            }
                            else
                            {
                                ctx.LoadAddress(list, listType);
                                ctx.LoadValue(listType.GetProperty("Count"));
                                ctx.CreateArray(itemType, null);
                                ctx.StoreValue(newArr);

                                ctx.LoadAddress(list, listType);
                                ctx.LoadValue(newArr);
                                ctx.LoadValue(0);
                            }

                            copyToArrayInt32Args[0] = expected; // // prefer: CopyTo(T[], int)
                            MethodInfo copyTo = listType.GetMethod("CopyTo", copyToArrayInt32Args);
                            if (copyTo == null)
                            { // fallback: CopyTo(Array, int)
                                copyToArrayInt32Args[1] = ctx.MapType(typeof(Array));
                                copyTo = listType.GetMethod("CopyTo", copyToArrayInt32Args);
                            }
                            ctx.EmitCall(copyTo);
                        }
                        ctx.LoadValue(newArr);
                    }
        }