Example #1
0
        void EmitNonNullWriter(WriterEmitContext ctx)
        {
            var il = ctx.Il;

            if (ctx.HasManifestToWrite)
            {
                ctx.WriteManifest();
            }

            using (ctx.GetLocal <int>(out var offset))
            {
                ctx.LoadCurrentOffset();
                il.Store(offset);

                // add 2 for the length of variable
                il.LoadIntValue(2);
                ctx.AddToCurrentOffset();

                Writer.EmitWrite(ctx);

                // stack empty, value written directly to the buffer

                ctx.LoadBuffer(offset); // stack: byte*

                ctx.LoadCurrentOffset();
                il.Load(offset);
                il.Emit(OpCodes.Sub); // stack: byte*, value

                il.LoadIntValue(2);
                il.Emit(OpCodes.Sub);                        // -2 for length

                il.StoreIndirectLittleEndian(typeof(short)); // save length
            }
        }
Example #2
0
            public void EmitWrite(WriterEmitContext context)
            {
                var il = context.Il;

                foreach (var field in fields)
                {
                    var writer = AllWriters.GetWriter(field);

                    var manifest = GetManifestValue(field);

                    void LoadValue()
                    {
                        il.Emit(writer.RequiresAddress ? OpCodes.Ldflda : OpCodes.Ldfld, field);
                    }

                    using (context.Scope(LoadValue, manifest: manifest))
                    {
                        // if the writer does not write manifest, this will write manifest for the writer
                        if (writer is IWriteManifest == false)
                        {
                            context.WriteManifest();
                        }

                        writer.EmitWrite(context);
                    }

                    if (writer is IUpdateOffset == false)
                    {
                        context.AddToCurrentOffset();
                    }
                }
            }
Example #3
0
        public void EmitWrite(WriterEmitContext context)
        {
            var nullable = typeof(TPrimitive?);

            var il = context.Il;

            var hasValue = il.DefineLabel();
            var end      = il.DefineLabel();

            context.LoadValue();
            il.EmitCall(OpCodes.Call, nullable.GetProperty(nameof(Nullable <int> .HasValue)).GetGetMethod(), null);
            il.Emit(OpCodes.Brtrue_S, hasValue);

            // no value, just store 0 and return length = 1

            if (context.HasManifestToWrite == false)
            {
                context.LoadBuffer();
                il.LoadIntValue(0);
                il.Emit(OpCodes.Stind_I1);
                il.LoadIntValue(1);
                il.Emit(OpCodes.Br, end); // jump to the end of writing
            }
            else
            {
                il.LoadIntValue(0);
                il.Emit(OpCodes.Br, end); // jump to the end of writing
            }

            // has value, store 1, then store value
            il.MarkLabel(hasValue);

            if (context.HasManifestToWrite == false)
            {
                context.LoadBuffer();
                il.LoadIntValue(1);
                il.Emit(OpCodes.Stind_I1);

                il.LoadIntValue(1);
                context.AddToCurrentOffset();
            }
            else
            {
                context.WriteManifest();
            }

            // load shifted buffer and value
            context.LoadBuffer();
            context.LoadValue();
            il.EmitCall(OpCodes.Call, nullable.GetProperty(nameof(Nullable <int> .Value)).GetGetMethod(), null);

            // emit regular
            Emit(context);
            il.MarkLabel(end);
        }