private void WriteFieldDeclaration(string name, UpdateField updateField, Type declarationType, bool declarationSettable)
        {
            declarationType = TypeHandler.ConvertToInterfaces(declarationType, rawName => RenameType(rawName));
            _header.Write($"        public {TypeHandler.GetFriendlyName(declarationType)} {name} {{ get;{(declarationSettable ? " set;" : "")} }}");
            if (typeof(DynamicUpdateField).IsAssignableFrom(updateField.Type))
            {
                _header.Write($" = new {TypeHandler.GetFriendlyName(declarationType)}();");
            }
            else if (updateField.Type.IsArray)
            {
                var typeFormat = TypeHandler.GetFriendlyName(declarationType.GetElementType());
                _header.Write($" = new {typeFormat}[{updateField.Size}]");
                if (typeof(DynamicUpdateField).IsAssignableFrom(updateField.Type.GetElementType()))
                {
                    _header.Write($" {{ ");
                    for (var i = 0; i < updateField.Size; ++i)
                    {
                        if (i != 0)
                        {
                            _header.Write(", ");
                        }

                        _header.Write($"new {typeFormat}()");
                    }
                    _header.Write(" }");
                }
                _header.Write(";");
            }

            _header.WriteLine();
        }
        public override IReadOnlyList <FlowControlBlock> OnField(string name, UpdateField updateField, IReadOnlyList <FlowControlBlock> previousControlFlow)
        {
            name = RenameField(name);

            var flowControl = new List <FlowControlBlock>();

            if (_create && updateField.Flag != UpdateFieldFlag.None)
            {
                flowControl.Add(new FlowControlBlock {
                    Statement = $"if ((flags & {updateField.Flag.ToFlagsExpression(" | ", "UpdateFieldFlag.", "", "(", ")")}) != UpdateFieldFlag.None)"
                });
            }

            var type                = updateField.Type;
            var outputFieldName     = name;
            var nextIndex           = string.Empty;
            var declarationType     = updateField.Type;
            var declarationSettable = true;
            var arrayLoopBlockIndex = -1;
            var indexLetter         = 'i';

            if (type.IsArray)
            {
                flowControl.Add(new FlowControlBlock {
                    Statement = $"for (var {indexLetter} = 0; {indexLetter} < {updateField.Size}; ++{indexLetter})"
                });
                outputFieldName    += $"[{indexLetter}]";
                type                = type.GetElementType();
                nextIndex          += ", " + indexLetter;
                declarationSettable = false;
                arrayLoopBlockIndex = flowControl.Count;
                ++indexLetter;
            }
            if (typeof(DynamicUpdateField).IsAssignableFrom(type))
            {
                flowControl.Add(new FlowControlBlock {
                    Statement = $"for (var {indexLetter} = 0; {indexLetter} < data.{outputFieldName}.Count; ++{indexLetter})"
                });
                if (!_create)
                {
                    flowControl.Add(new FlowControlBlock {
                        Statement = $"if (data.{outputFieldName}.UpdateMask[{indexLetter}])"
                    });
                }

                outputFieldName    += $"[{indexLetter}]";
                type                = type.GenericTypeArguments[0];
                nextIndex          += ", " + indexLetter;
                declarationSettable = false;
                ++indexLetter;
            }
            if (typeof(BlzVectorField).IsAssignableFrom(type))
            {
                flowControl.Add(new FlowControlBlock {
                    Statement = $"for (var {indexLetter} = 0; {indexLetter} < data.{outputFieldName}.Length; ++{indexLetter})"
                });
                outputFieldName += $"[{indexLetter}]";
                type             = type.GenericTypeArguments[0];
                nextIndex       += ", " + indexLetter;
                declarationType  = type.MakeArrayType();
                ++indexLetter;
            }
            if (typeof(BlzOptionalField).IsAssignableFrom(type))
            {
                flowControl.Add(new FlowControlBlock {
                    Statement = $"if (has{name})"
                });
                type            = type.GenericTypeArguments[0];
                declarationType = type;
            }
            if (typeof(Bits).IsAssignableFrom(type))
            {
                declarationType = typeof(uint);
            }

            if (!_create && _writeUpdateMasks)
            {
                GenerateBitIndexConditions(updateField, name, flowControl, previousControlFlow, arrayLoopBlockIndex);
                if (name.EndsWith("is_initialized()"))
                {
                    flowControl.RemoveAt(1); // bit generated but not checked for is_initialized
                }
            }

            Type interfaceType = null;

            if (updateField.SizeForField != null)
            {
                type          = (updateField.SizeForField.GetValue(null) as UpdateField).Type;
                type          = type.GenericTypeArguments[0];
                interfaceType = TypeHandler.ConvertToInterfaces(type, rawName => RenameType(rawName));
            }

            RegisterDynamicChangesMaskFieldType(type);

            _fieldWrites.Add((name, false, (pcf) =>
            {
                WriteControlBlocks(_source, flowControl, pcf);
                WriteField(name, outputFieldName, type, updateField.BitSize, nextIndex, interfaceType);
                _indent = 3;
                return(flowControl);
            }
                              ));

            if (_create && updateField.SizeForField == null && declarationType.GetCustomAttribute <DontStoreInWowPacketParserAttribute>() == null)
            {
                WriteFieldDeclaration(name, updateField, declarationType, declarationSettable);
            }

            return(flowControl);
        }