Ejemplo n.º 1
0
        public void EmitDeserialize(Emit emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();

            //value = new Type[100];
            emiter.LoadConstant(100);
            emiter.NewArray(elementType);
            emiter.StoreLocal(value);

            var loop      = emiter.DefineLabel();
            var loopCheck = emiter.DefineLabel();

            using (var ex = emiter.DeclareLocal <Exception>("_ex"))
                using (var element = emiter.DeclareLocal(elementType, "element"))
                    using (var i = emiter.DeclareLocal <int>("i"))
                    {
                        emiter.MarkLabel(loop);

                        var eb = emiter.BeginExceptionBlock();
                        if (_compiler != null)
                        {
                            _compiler.EmitDeserialize(emiter, element);
                        }
                        else if (_serializer != null)
                        {
                            emiter.CallDeserializer(_serializer, element);
                        }
                        else
                        {
                            emiter.CallDeserializerForType(elementType, element);
                        }
                        var cb = emiter.BeginCatchBlock <Exception>(eb);
                        emiter.StoreLocal(ex);
                        emiter.EndCatchBlock(cb);
                        emiter.EndExceptionBlock(eb);

                        // value[i] = element
                        emiter.LoadLocal(value);
                        emiter.LoadLocal(i);
                        emiter.LoadLocal(element);
                        emiter.StoreElement(elementType);

                        // ++i
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(1);
                        emiter.Add();
                        emiter.StoreLocal(i);

                        // i < length
                        emiter.MarkLabel(loopCheck);
                        emiter.LoadLocal(i);
                        emiter.LoadConstant(100);
                        emiter.BranchIfLess(loop);
                    }
        }
        public void EmitDeserialize(Emit emiter, Local value)
        {
            var elementType = value.LocalType.GetElementType();
            var emptyArray  = emiter.DefineLabel();
            var end         = emiter.DefineLabel();

            using (var length = emiter.DeclareLocal <int>("length"))
            {
                emiter.CallDeserializerForType(length.LocalType, length);

                // if(length < 1) {
                //  value = Array.Empty<>()
                //  return
                // }
                emiter.LoadLocal(length);
                emiter.LoadConstant(1);
                emiter.BranchIfLess(emptyArray);

                // value = new [length]
                emiter.LoadLocal(length);
                emiter.NewArray(elementType);
                emiter.StoreLocal(value);

                var loop      = emiter.DefineLabel();
                var loopCheck = emiter.DefineLabel();

                // Little optimization for byte arrays
                if (elementType == typeof(byte))
                {
                    // value = reader.ReadBytes(length);
                    emiter.LoadArgument(1);
                    emiter.LoadLocal(length);
                    emiter.CallVirtual(typeof(BinaryReader).GetMethod(nameof(BinaryReader.ReadBytes)));
                    emiter.StoreLocal(value);
                    emiter.Branch(end);
                }
                else
                {
                    using (var element = emiter.DeclareLocal(elementType, "element"))
                        using (var i = emiter.DeclareLocal <int>("i"))
                        {
                            emiter.MarkLabel(loop);

                            if (_compiler != null)
                            {
                                _compiler.EmitDeserialize(emiter, element);
                            }
                            else if (_serializer != null)
                            {
                                emiter.CallDeserializer(_serializer, element);
                            }
                            else
                            {
                                emiter.CallDeserializerForType(elementType, element);
                            }

                            // value[i] = element
                            emiter.LoadLocal(value);
                            emiter.LoadLocal(i);
                            emiter.LoadLocal(element);
                            emiter.StoreElement(elementType);

                            // ++i
                            emiter.LoadLocal(i);
                            emiter.LoadConstant(1);
                            emiter.Add();
                            emiter.StoreLocal(i);

                            // i < length
                            emiter.MarkLabel(loopCheck);
                            emiter.LoadLocal(i);
                            emiter.LoadLocal(length);
                            emiter.BranchIfLess(loop);
                        }
                }

                emiter.Branch(end);
            }

            // value = Array.Empty<>()
            emiter.MarkLabel(emptyArray);
            emiter.Call(typeof(Array)
                        .GetMethod(nameof(Array.Empty))
                        .GetGenericMethodDefinition()
                        .MakeGenericMethod(elementType));
            emiter.StoreLocal(value);
            emiter.MarkLabel(end);
        }