ManifestComparator.h (5202B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #pragma once 4 #include <winget/Manifest.h> 5 #include <memory> 6 #include <optional> 7 #include <string> 8 #include <string_view> 9 #include <utility> 10 #include <vector> 11 12 13 namespace AppInstaller::Manifest 14 { 15 // Flags to indicate why an installer was not applicable 16 enum class InapplicabilityFlags : int 17 { 18 None = 0x0, 19 OSVersion = 0x1, 20 InstalledScope = 0x2, 21 InstalledType = 0x4, 22 InstalledLocale = 0x8, 23 Locale = 0x10, 24 Scope = 0x20, 25 MachineArchitecture = 0x40, 26 Market = 0x80, 27 InstallerType = 0x100, 28 }; 29 30 DEFINE_ENUM_FLAG_OPERATORS(InapplicabilityFlags); 31 32 namespace details 33 { 34 // An interface for defining new filters based on user inputs. 35 struct FilterField 36 { 37 FilterField(std::string_view name) : m_name(name) {} 38 39 virtual ~FilterField() = default; 40 41 std::string_view Name() const { return m_name; } 42 43 // Determines if the installer is applicable based on this field alone. 44 virtual InapplicabilityFlags IsApplicable(const AppInstaller::Manifest::ManifestInstaller& installer) = 0; 45 46 // Explains why the filter regarded this installer as inapplicable. 47 // Will only be called when IsApplicable returns false. 48 virtual std::string ExplainInapplicable(const AppInstaller::Manifest::ManifestInstaller& installer) = 0; 49 50 private: 51 std::string_view m_name; 52 }; 53 54 // The result of ComparisonField::IsFirstBetter 55 enum class ComparisonResult 56 { 57 // The first input is not better than the second input. 58 Negative, 59 // The first input is somewhat better than the second input. 60 // If another comparison has a strong positive result, it will override a weak result. 61 WeakPositive, 62 // The first input is definitely better than the second input. 63 StrongPositive, 64 }; 65 66 // An interface for defining new comparisons based on user inputs. 67 struct ComparisonField : public FilterField 68 { 69 using FilterField::FilterField; 70 71 virtual ~ComparisonField() = default; 72 73 // Determines if the first installer is a better choice based on this field alone. 74 virtual ComparisonResult IsFirstBetter(const AppInstaller::Manifest::ManifestInstaller& first, const AppInstaller::Manifest::ManifestInstaller& second) = 0; 75 }; 76 } 77 78 struct InstallerAndInapplicabilities 79 { 80 std::optional<AppInstaller::Manifest::ManifestInstaller> installer; 81 std::vector<InapplicabilityFlags> inapplicabilitiesInstaller; 82 }; 83 84 // Class in charge of comparing manifest entries 85 struct ManifestComparator 86 { 87 // Options that affect the comparisons. 88 struct Options 89 { 90 // The allowed architectures and a value indicating whether to perform applicability checks. 91 std::vector<Utility::Architecture> AllowedArchitectures; 92 bool SkipApplicabilityCheck = false; 93 94 // The requested installer type. 95 std::optional<InstallerTypeEnum> RequestedInstallerType; 96 97 // The currently installed type. 98 std::optional<InstallerTypeEnum> CurrentlyInstalledType; 99 100 // The requested installer scope and a value indicating whether and unknown scope is acceptable. 101 std::optional<ScopeEnum> RequestedInstallerScope; 102 std::optional<bool> AllowUnknownScope; 103 104 // The currently installed scope. 105 std::optional<ScopeEnum> CurrentlyInstalledScope; 106 107 // The requested installer locale. 108 std::optional<std::string> RequestedInstallerLocale; 109 110 // Get the currently installed locale intent and value. 111 std::optional<std::string> PreviousUserIntentLocale; 112 std::optional<std::string> CurrentlyInstalledLocale; 113 }; 114 115 ManifestComparator(const Options& options); 116 117 // Gets the best installer from the manifest, if at least one is applicable. 118 InstallerAndInapplicabilities GetPreferredInstaller(const AppInstaller::Manifest::Manifest& manifest); 119 120 // Determines if an installer is applicable. 121 InapplicabilityFlags IsApplicable(const AppInstaller::Manifest::ManifestInstaller& installer); 122 123 // Determines if the first installer is a better choice. 124 bool IsFirstBetter( 125 const AppInstaller::Manifest::ManifestInstaller& first, 126 const AppInstaller::Manifest::ManifestInstaller& second); 127 128 private: 129 void AddFilter(std::unique_ptr<details::FilterField>&& filter); 130 void AddComparator(std::unique_ptr<details::ComparisonField>&& comparator); 131 132 std::vector<std::unique_ptr<details::FilterField>> m_filters; 133 // Non-owning pointers to values in m_filters. 134 std::vector<details::ComparisonField*> m_comparators; 135 }; 136 137 }