예제 #1
0
        public void EmitSerialize(CompilerContext context, Local value)
        {
            using (var address = context.Emit.DeclareLocal <string>("str"))
                using (var port = context.Emit.DeclareLocal <ushort>("port"))
                {
                    var isNullLabel = context.Emit.DefineLabel();
                    var writeLabel  = context.Emit.DefineLabel();

                    // if (value == null) goto isNull
                    context.Emit.LoadLocal(value);
                    context.Emit.LoadNull();
                    context.Emit.BranchIfEqual(isNullLabel);

                    // address = value.Address.ToString()
                    context.Emit.LoadLocal(value);
                    context.Emit.Call(typeof(IPEndPoint).GetProperty(nameof(IPEndPoint.Address)).GetMethod);
                    context.Emit.CallVirtual(ReflectionHelper.GetMethod((IPEndPoint _) => _.ToString()));
                    context.Emit.StoreLocal(address);

                    // port = (ushort)value.Port
                    context.Emit.LoadLocal(value);
                    context.Emit.Call(typeof(IPEndPoint).GetProperty(nameof(IPEndPoint.Port)).GetMethod);
                    context.Emit.Convert <ushort>();
                    context.Emit.StoreLocal(port);
                    context.Emit.Branch(writeLabel);

                    context.Emit.MarkLabel(isNullLabel);

                    // address = "255.255.255.255"
                    context.Emit.LoadConstant("255.255.255.255");
                    context.Emit.StoreLocal(address);

                    context.Emit.MarkLabel(writeLabel);

                    // ProudNetBinaryWriterExtensions.WriteProudString(writer, address, false)
                    context.Emit.LoadReaderOrWriterParam();
                    context.Emit.LoadLocal(address);
                    context.Emit.LoadConstant(false);
                    context.Emit.Call(ReflectionHelper.GetMethod((BinaryWriter _) => _.WriteProudString(default(string), default(bool))));

                    // writer.Write(port)
                    context.EmitSerialize(port);
                }
        }
        public void EmitSerialize(CompilerContext context, Local value)
        {
            var elementType = value.LocalType.GetElementType();

            using (var length = context.Emit.DeclareLocal <int>("length"))
            {
                var writeLabel = context.Emit.DefineLabel();

                // if (value != null) goto write
                context.Emit.LoadLocal(value);
                context.Emit.LoadNull();
                context.Emit.CompareEqual();
                context.Emit.BranchIfFalse(writeLabel);

                // value = Array.Empty<>()
                context.Emit.Call(typeof(Array)
                                  .GetMethod(nameof(Array.Empty))
                                  .GetGenericMethodDefinition()
                                  .MakeGenericMethod(elementType));
                context.Emit.StoreLocal(value);

                // length = value.Length
                context.Emit.MarkLabel(writeLabel);
                context.Emit.LoadLocal(value);
                context.Emit.Call(value.LocalType.GetProperty(nameof(Array.Length)).GetMethod);
                context.Emit.StoreLocal(length);

                // ProudNetBinaryWriterExtensions.WriteScalar(writer, length)
                context.Emit.LoadReaderOrWriterParam();
                context.Emit.LoadLocal(length);
                context.Emit.Call(ReflectionHelper.GetMethod((BinaryWriter _) => _.WriteScalar(default(int))));

                var loopLabel      = context.Emit.DefineLabel();
                var loopCheckLabel = context.Emit.DefineLabel();

                using (var element = context.Emit.DeclareLocal(elementType, "element"))
                    using (var i = context.Emit.DeclareLocal <int>("i"))
                    {
                        context.Emit.Branch(loopCheckLabel);
                        context.Emit.MarkLabel(loopLabel);

                        // element = value[i]
                        context.Emit.LoadLocal(value);
                        context.Emit.LoadLocal(i);
                        context.Emit.LoadElement(elementType);
                        context.Emit.StoreLocal(element);

                        context.EmitSerialize(element);

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

                        // i < length
                        context.Emit.MarkLabel(loopCheckLabel);
                        context.Emit.LoadLocal(i);
                        context.Emit.LoadLocal(length);
                        context.Emit.BranchIfLess(loopLabel);
                    }
            }
        }