public void Execute(IServiceCollection target)
        {
            var enums = new Dictionary <string, EnumElement>();

            foreach (var vkEnum in this.xmlCache.GetVkXml().Element("registry").Elements("enums"))
            {
                string name = vkEnum.Attribute("name").Value;
                string type = vkEnum.Attribute("type")?.Value;

                string   extension = null;
                string[] nameParts = name == "API Constants"
                                        ? new[] { name }
                                        : this.nameParser.GetNameParts(name, out extension);

                var newEnum = new EnumElement
                {
                    VkName             = name,
                    Type               = type,
                    NameParts          = nameParts,
                    ExtensionNamespace = extension
                };

                foreach (var vkField in vkEnum.Elements("enum"))
                {
                    string fieldName = vkField.Attribute("name").Value;
                    bool   isBitmask = true;
                    string value     = vkField.Attribute("bitpos")?.Value;
                    string comment   = SimpleParser.NormaliseComment(vkField.Attribute("comment")?.Value);

                    if (value == null)
                    {
                        isBitmask = false;
                        value     = vkField.Attribute("value")?.Value;

                        // Special case for mapping C "unsigned long long"
                        // (64-bit unsigned integer) to C# UInt64
                        if (value == "(~0ULL)")
                        {
                            value = "(~0UL)";
                        }

                        value = value?.Trim('(', ')');
                    }

                    IEnumerable <string> fieldNameParts = this.nameParser.ParseEnumField(fieldName, nameParts);

                    newEnum.Fields.Add(fieldName, new EnumField
                    {
                        VkName    = fieldName,
                        NameParts = fieldNameParts.ToArray(),
                        IsBitmask = isBitmask,
                        Value     = value,
                        Comment   = comment != null ? new List <string> {
                            comment
                        } : null
                    });
                }

                enums.Add(name, newEnum);
            }


            foreach (var vkExtension in this.xmlCache.GetVkXml()
                     .Element("registry")
                     .Element("extensions")
                     .Elements("extension"))
            {
                int    extensionNumber = int.Parse(vkExtension.Attribute("number").Value);
                string extensionName   = vkExtension.Attribute("name").Value;

                var extensionNameParts = extensionName.Split('_');

                string extensionSuffix = extensionNameParts[1].ToLower().FirstToUpper();

                foreach (var vkExtensionEnum in vkExtension.Elements("require")
                         .SelectMany(x => x.Elements("enum"))
                         .Where(x => x.Attribute("extends") != null))
                {
                    string vkName       = vkExtensionEnum.Attribute("name").Value;
                    var    extendedEnum = enums[vkExtensionEnum.Attribute("extends").Value];

                    int? value     = null;
                    bool isBitmask = false;

                    if (vkExtensionEnum.Attribute("offset") != null)
                    {
                        int offset = int.Parse(vkExtensionEnum.Attribute("offset").Value);

                        value = 1000000000 + 1000 * (extensionNumber - 1) + offset;
                    }
                    else if (vkExtensionEnum.Attribute("bitpos") != null)
                    {
                        value     = int.Parse(vkExtensionEnum.Attribute("bitpos").Value);
                        isBitmask = true;
                    }
                    else if (vkExtensionEnum.Attribute("value") != null)
                    {
                        value = int.Parse(vkExtensionEnum.Attribute("value").Value);
                    }

                    if (vkExtensionEnum.Attribute("dir")?.Value == "-")
                    {
                        value = -value;
                    }

                    var nameParts = this.nameParser.ParseEnumField(vkName, extendedEnum.NameParts);

                    extendedEnum.Fields[vkName] = new EnumField
                    {
                        VkName             = vkName,
                        Value              = value?.ToString(),
                        NameParts          = nameParts.ToArray(),
                        IsBitmask          = isBitmask,
                        ExtensionNamespace = extensionSuffix
                    };
                }
            }

            foreach (var element in enums.Values)
            {
                target.AddSingleton(element);
            }
        }
        public void Execute(IServiceCollection services)
        {
            var newCommands = new Dictionary <string, CommandElement>();

            foreach (var vkCommand in this.xmlCache.GetVkXml().Element("registry").Element("commands").Elements("command"))
            {
                if (vkCommand.Element("proto") == null)
                {
                    continue;
                }
                string name = vkCommand.Element("proto").Element("name").Value;
                string type = vkCommand.Element("proto").Element("type").Value;

                string[] nameParts = this.nameParser.GetNameParts(name, out string extension);

                string[] verbExceptions = new[] { "cmd", "queue", "device" };

                string verb = verbExceptions.Contains(nameParts[0]) ? nameParts[1] : nameParts[0];

                string[] successCodes = vkCommand.Attribute("successcodes")?.Value?.Split(',');

                var newCommand = new CommandElement
                {
                    VkName             = name,
                    Type               = type,
                    NameParts          = nameParts,
                    ExtensionNamespace = extension,
                    Verb               = verb,
                    SuccessCodes       = successCodes
                };

                newCommands.Add(name, newCommand);

                foreach (var vkParam in vkCommand.Elements("param"))
                {
                    var nameElement = vkParam.Element("name");

                    string paramName = nameElement.Value;
                    string paramType = vkParam.Element("type").Value;
                    bool.TryParse(vkParam.Attribute("optional")?.Value, out bool isOptional);
                    bool.TryParse(vkParam.Attribute("noAutoValidity")?.Value, out bool noAutoValidity);

                    var typeNodes   = nameElement.NodesBeforeSelf();
                    var pointerType = PointerTypeUtil.GetFrom(typeNodes);

                    var lenField   = vkParam.Attribute("len");
                    var dimensions = lenField != null
                                        ? SimpleParser.ParsedLenField(lenField.Value)
                                        : null;

                    string[] paramNameParts = this.nameParser.ParseParamName(paramName, pointerType, out string paramExtension);

                    newCommand.Params.Add(new ParamElement
                    {
                        VkName             = paramName,
                        Type               = paramType,
                        PointerType        = pointerType,
                        NameParts          = paramNameParts,
                        ExtensionNamespace = paramExtension,
                        IsOptional         = isOptional,
                        NoAutoValidity     = noAutoValidity,
                        Dimensions         = dimensions
                    });
                }
            }

            foreach (var commandRequirement in this.xmlCache.GetVkXml().Element("registry").Elements("feature").SelectMany(feature => feature.Elements("require").SelectMany(x => x.Elements("command"))))
            {
                services.AddSingleton(newCommands[commandRequirement.Attribute("name").Value]);
            }

            foreach (var extension in this.xmlCache.GetVkXml().Element("registry").Element("extensions").Elements("extension"))
            {
                if (extension.Attribute("supported").Value == "vulkan" && extension.Attribute("promotedto") == null)
                {
                    foreach (string commandRequirement in extension.Elements("require")
                             .SelectMany(x => x.Elements("command"))
                             .Select(x => x.Attribute("name").Value)
                             .Distinct())
                    {
                        services.AddSingleton(newCommands[commandRequirement]);
                    }
                }
            }
        }