/*serialization of entire list. generates code like:
         *
         *  static public void WriteStructBuf(NetworkWriter writer, SyncListBuf items)
         *  {
         *      ushort count = (ushort)items.Count;
         *      writer.Write(count);
         *      for (ushort i=0; i < count; i++)
         *      {
         *          items.SerializeItem(writer, items.GetItem(i));
         *      }
         *  }
         */
        void GenerateWriteFunc(MethodReference writeItemFunc)
        {
            var functionName = "_WriteStruct" + m_TypeDef.GetElementType().Name + "_";

            if (m_TypeDef.DeclaringType != null)
            {
                functionName += m_TypeDef.DeclaringType.Name;
            }
            else
            {
                functionName += "None";
            }

            // create new writer for this type
            MethodDefinition writerFunc = new MethodDefinition(functionName,
                                                               MethodAttributes.Public |
                                                               MethodAttributes.Static |
                                                               MethodAttributes.HideBySig,
                                                               Weaver.voidType);

            writerFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType)));
            writerFunc.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(m_TypeDef)));

            writerFunc.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type));
            writerFunc.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type));
            writerFunc.Body.InitLocals = true;

            ILProcessor worker = writerFunc.Body.GetILProcessor();

            worker.Append(worker.Create(OpCodes.Ldarg_1));

            // call the generic Count from the base class
            var getCount      = Weaver.ResolveMethod(Weaver.SyncListStructType, "get_Count");
            var getCountTyped = Helpers.MakeHostInstanceGeneric(getCount, m_ItemType);

            worker.Append(worker.Create(OpCodes.Callvirt, getCountTyped));

            worker.Append(worker.Create(OpCodes.Stloc_0));
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            worker.Append(worker.Create(OpCodes.Callvirt, Weaver.NetworkWriteUInt16));
            worker.Append(worker.Create(OpCodes.Ldc_I4_0));
            worker.Append(worker.Create(OpCodes.Stloc_1));

            var loopCheckLabel = worker.Create(OpCodes.Nop);

            worker.Append(worker.Create(OpCodes.Br, loopCheckLabel));

            //loop start
            var loopStartLabel = worker.Create(OpCodes.Nop);

            worker.Append(loopStartLabel);

            worker.Append(worker.Create(OpCodes.Ldarg_1));
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Ldarg_1));
            worker.Append(worker.Create(OpCodes.Ldloc_1));

            // call the generic [] from the base class
            var getItem      = Weaver.ResolveMethod(Weaver.SyncListStructType, "GetItem");
            var getItemTyped = Helpers.MakeHostInstanceGeneric(getItem, m_ItemType);

            worker.Append(worker.Create(OpCodes.Callvirt, getItemTyped));
            worker.Append(worker.Create(OpCodes.Callvirt, writeItemFunc));

            worker.Append(worker.Create(OpCodes.Ldloc_1));
            worker.Append(worker.Create(OpCodes.Ldc_I4_1));
            worker.Append(worker.Create(OpCodes.Add));
            worker.Append(worker.Create(OpCodes.Conv_U2));
            worker.Append(worker.Create(OpCodes.Stloc_1));

            worker.Append(loopCheckLabel);
            worker.Append(worker.Create(OpCodes.Ldloc_1));
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            worker.Append(worker.Create(OpCodes.Blt, loopStartLabel));

            worker.Append(worker.Create(OpCodes.Ret));

            Weaver.RegisterWriteFunc(m_TypeDef.FullName, writerFunc);
        }