Arbiter
Dependency manager library that supports decentralization
Requirement.h
Go to the documentation of this file.
1 #pragma once
2 
3 #ifndef __cplusplus
4 #error "This file must be compiled as C++."
5 #endif
6 
7 #include <arbiter/Requirement.h>
8 
9 #include "Types.h"
10 #include "Version.h"
11 
12 #include <cassert>
13 #include <memory>
14 #include <ostream>
15 
16 namespace Arbiter {
17 namespace Requirement {
18 
19 class Visitor;
20 
21 } // namespace Requirement
22 } // namespace Arbiter
23 
25 {
26  public:
27  /**
28  * Returns whether this requirement would be satisfied by using the given
29  * selected version.
30  */
31  virtual bool satisfiedBy (const ArbiterSelectedVersion &selectedVersion) const = 0;
32 
33  /**
34  * Returns the priority of this requirement.
35  */
36  virtual int priority () const noexcept
37  {
38  return 0;
39  }
40 
41  /**
42  * Attempts to create a requirement which expresses the intersection of this
43  * requirement and the given one
44  *
45  * In other words, this attempts to find the loosest possible requirement
46  * which is a superset of the two inputs. Any version which passes the
47  * intersected requirement would also pass either one of the original
48  * inputs.
49  *
50  * Returns `nullptr` if no intersection is possible.
51  */
52  virtual std::unique_ptr<ArbiterRequirement> intersect (const ArbiterRequirement &rhs) const = 0;
53 
54  /**
55  * Visits the requirement, then any child requirements.
56  *
57  * The default implementation simply visits this requirement.
58  */
59  virtual void visit (Arbiter::Requirement::Visitor &visitor) const;
60 
61  std::unique_ptr<ArbiterRequirement> cloneRequirement () const;
62  virtual size_t hash () const noexcept = 0;
63 };
64 
65 namespace Arbiter {
66 namespace Requirement {
67 
68 /**
69  * Base class for objects that want to visit requirements.
70  */
71 class Visitor
72 {
73  public:
74  virtual ~Visitor () = default;
75 
76  virtual void operator() (const ArbiterRequirement &requirement) = 0;
77 };
78 
79 /**
80  * A requirement satisfied by any version.
81  */
82 class Any final : public ArbiterRequirement
83 {
84  public:
85  bool satisfiedBy (const ArbiterSemanticVersion &) const noexcept
86  {
87  return true;
88  }
89 
91  {
92  return true;
93  }
94 
95  bool operator== (const Arbiter::Base &other) const override
96  {
97  return (bool)dynamic_cast<const Any *>(&other);
98  }
99 
101  {
102  return std::make_unique<Any>(*this);
103  }
104 
105  std::ostream &describe (std::ostream &os) const override;
106  std::unique_ptr<ArbiterRequirement> intersect (const ArbiterRequirement &rhs) const override;
107 
108  size_t hash () const noexcept override
109  {
110  return 4;
111  }
112 };
113 
114 /**
115  * A requirement satisfied only by versions greater than or equal to the
116  * specified one.
117  */
118 class AtLeast final : public ArbiterRequirement
119 {
120  public:
121  ArbiterSemanticVersion _minimumVersion;
122 
123  explicit AtLeast (ArbiterSemanticVersion version) noexcept
125  {}
126 
128  {
131  } else {
132  return false;
133  }
134  }
135 
137  {
138  return std::make_unique<AtLeast>(*this);
139  }
140 
142  std::ostream &describe (std::ostream &os) const override;
143  bool operator== (const Arbiter::Base &other) const override;
144  std::unique_ptr<ArbiterRequirement> intersect (const ArbiterRequirement &rhs) const override;
145  size_t hash () const noexcept override;
146 };
147 
148 /**
149  * A requirement satisfied only by versions which are "compatible with" the
150  * specified one, as defined by SemVer.
151  */
152 class CompatibleWith final : public ArbiterRequirement
153 {
154  public:
155  ArbiterSemanticVersion _baseVersion;
156  ArbiterRequirementStrictness _strictness;
157 
158  explicit CompatibleWith (ArbiterSemanticVersion version, ArbiterRequirementStrictness strictness) noexcept
161  {}
162 
164  {
167  } else {
168  return false;
169  }
170  }
171 
173  {
174  return std::make_unique<CompatibleWith>(*this);
175  }
176 
178  std::ostream &describe (std::ostream &os) const override;
179  bool operator== (const Arbiter::Base &other) const override;
180  std::unique_ptr<ArbiterRequirement> intersect (const ArbiterRequirement &rhs) const override;
181  size_t hash () const noexcept override;
182 };
183 
184 /**
185  * A requirement satisfied only by one particular semantic version.
186  */
187 class Exactly final : public ArbiterRequirement
188 {
189  public:
190  ArbiterSemanticVersion _version;
191 
192  explicit Exactly (ArbiterSemanticVersion version) noexcept
193  : _version(std::move(version))
194  {}
195 
197  {
200  } else {
201  return false;
202  }
203  }
204 
206  {
207  return std::make_unique<Exactly>(*this);
208  }
209 
211  std::ostream &describe (std::ostream &os) const override;
212  bool operator== (const Arbiter::Base &other) const override;
213  std::unique_ptr<ArbiterRequirement> intersect (const ArbiterRequirement &rhs) const override;
214  size_t hash () const noexcept override;
215 };
216 
217 class Unversioned final : public ArbiterRequirement
218 {
219  public:
220  // This metadata is not really part of the requirement type; it is
221  // associated with the selected version.
222  using Metadata = Arbiter::SharedUserValue<ArbiterSelectedVersion>;
223 
224  Metadata _metadata;
225 
226  explicit Unversioned (Metadata metadata)
228  {}
229 
230  std::unique_ptr<Base> clone () const override
231  {
232  return std::make_unique<Unversioned>(*this);
233  }
234 
235  std::ostream &describe (std::ostream &os) const override;
236  bool satisfiedBy (const ArbiterSelectedVersion &selectedVersion) const override;
237  std::unique_ptr<ArbiterRequirement> intersect (const ArbiterRequirement &rhs) const override;
238  bool operator== (const Arbiter::Base &other) const override;
239  size_t hash () const noexcept override;
240 };
241 
242 class Custom final : public ArbiterRequirement
243 {
244  public:
245  explicit Custom (ArbiterRequirementPredicate predicate, std::shared_ptr<const void> context)
246  : _predicate(std::move(predicate))
247  , _context(std::move(context))
248  {
249  assert(_predicate);
250  }
251 
252  std::ostream &describe (std::ostream &os) const override
253  {
254  return os << "(custom predicate)";
255  }
256 
257  std::unique_ptr<Base> clone () const override
258  {
259  return std::make_unique<Custom>(*this);
260  }
261 
262  bool satisfiedBy (const ArbiterSelectedVersion &selectedVersion) const override;
263  std::unique_ptr<ArbiterRequirement> intersect (const ArbiterRequirement &rhs) const override;
264  bool operator== (const Arbiter::Base &other) const override;
265  size_t hash () const noexcept override;
266 
267  private:
268  ArbiterRequirementPredicate _predicate;
269  std::shared_ptr<const void> _context;
270 };
271 
272 class Compound final : public ArbiterRequirement
273 {
274  public:
275  std::vector<std::shared_ptr<ArbiterRequirement>> _requirements;
276 
277  explicit Compound (std::vector<std::shared_ptr<ArbiterRequirement>> requirements)
278  : _requirements(std::move(requirements))
279  {}
280 
281  std::unique_ptr<Base> clone () const override
282  {
283  return std::make_unique<Compound>(*this);
284  }
285 
286  /**
287  * Returns the minimum priority index of all the requirements held by this
288  * compound requirement.
289  */
290  int priority () const noexcept override;
291 
292  bool satisfiedBy (const ArbiterSelectedVersion &selectedVersion) const override;
293  std::unique_ptr<ArbiterRequirement> intersect (const ArbiterRequirement &rhs) const override;
294  std::ostream &describe (std::ostream &os) const override;
295  bool operator== (const Arbiter::Base &other) const override;
296  size_t hash () const noexcept override;
297  void visit (Visitor &visitor) const override;
298 };
299 
300 class Prioritized final : public ArbiterRequirement
301 {
302  public:
304 
305  explicit Prioritized (std::shared_ptr<ArbiterRequirement> requirement, int priority)
306  : _requirement(std::move(requirement))
307  , _priority(priority)
308  {}
309 
310  std::unique_ptr<Base> clone () const override
311  {
312  return std::make_unique<Prioritized>(*this);
313  }
314 
316  {
317  return _priority;
318  }
319 
321  std::unique_ptr<ArbiterRequirement> intersect (const ArbiterRequirement &rhs) const override;
322  std::ostream &describe (std::ostream &os) const override;
323  bool operator== (const Arbiter::Base &other) const override;
324  size_t hash () const noexcept override;
325  void visit (Visitor &visitor) const override;
326 
327  private:
328  int _priority;
329 };
330 
331 } // namespace Requirement
332 } // namespace Arbiter
333 
334 namespace std {
335 
336 template<>
337 struct hash<ArbiterRequirement> final
338 {
339  public:
340  size_t operator() (const ArbiterRequirement &requirement) const
341  {
342  return requirement.hash();
343  }
344 };
345 
346 } // namespace std
std::ostream & describe(std::ostream &os) const override
Definition: Requirement.h:252
std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const override
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
bool satisfiedBy(const ArbiterSelectedVersion &selectedVersion) const override
Returns whether this requirement would be satisfied by using the given selected version.
bool satisfiedBy(const ArbiterSemanticVersion &version) const noexcept
ArbiterSemanticVersion _baseVersion
Definition: Requirement.h:155
bool operator==(const Arbiter::Base &other) const override
int priority() const noexcept override
Returns the minimum priority index of all the requirements held by this compound requirement.
std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const override
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
size_t hash() const noexcept override
std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const override
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
auto makeIteratorRange(const Collection &collection)
Creates an IteratorRange encompassing the entirety of the given read-only collection.
Definition: Iterator.h:45
bool operator==(const Arbiter::Base &other) const override
std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const override
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
Unversioned(Metadata metadata)
Definition: Requirement.h:226
bool operator==(const Arbiter::Base &other) const override
ArbiterSemanticVersion _minimumVersion
Definition: Requirement.h:121
std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const override
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
bool operator==(const Arbiter::Base &other) const override
std::shared_ptr< ArbiterRequirement > _requirement
Definition: Requirement.h:303
std::ostream & describe(std::ostream &os) const override
virtual int priority() const noexcept
Returns the priority of this requirement.
Definition: Requirement.h:36
bool satisfiedBy(const ArbiterSelectedVersion &selectedVersion) const override
Returns whether this requirement would be satisfied by using the given selected version.
size_t hash() const noexcept override
size_t hash() const noexcept override
Definition: Requirement.h:108
virtual ~Visitor()=default
std::ostream & describe(std::ostream &os) const override
size_t hash() const noexcept override
virtual void visit(Arbiter::Requirement::Visitor &visitor) const
Visits the requirement, then any child requirements.
Exactly(ArbiterSemanticVersion version) noexcept
Definition: Requirement.h:192
std::ostream & describe(std::ostream &os) const override
std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const override
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
std::unique_ptr< Base > clone() const override
Definition: Requirement.h:257
ArbiterSemanticVersion _version
Definition: Requirement.h:190
Custom(ArbiterRequirementPredicate predicate, std::shared_ptr< const void > context)
Definition: Requirement.h:245
std::unique_ptr< ArbiterRequirement > cloneRequirement() const
virtual void operator()(const ArbiterRequirement &requirement)=0
bool satisfiedBy(const ArbiterSemanticVersion &version) const noexcept
Compound(std::vector< std::shared_ptr< ArbiterRequirement >> requirements)
Definition: Requirement.h:277
virtual size_t hash() const noexcept=0
std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const override
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const override
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
bool operator==(const Arbiter::Base &other) const override
size_t operator()(const ArbiterRequirement &requirement) const
Definition: Requirement.h:340
size_t hash() const noexcept override
AtLeast(ArbiterSemanticVersion version) noexcept
Definition: Requirement.h:123
std::unique_ptr< Base > clone() const override
Definition: Requirement.h:230
Prioritized(std::shared_ptr< ArbiterRequirement > requirement, int priority)
Definition: Requirement.h:305
CompatibleWith(ArbiterSemanticVersion version, ArbiterRequirementStrictness strictness) noexcept
Definition: Requirement.h:158
size_t hash() const noexcept override
std::ostream & describe(std::ostream &os) const override
bool satisfiedBy(const ArbiterSemanticVersion &) const noexcept
Definition: Requirement.h:85
bool operator==(const Arbiter::Base &other) const override
ArbiterRequirementStrictness _strictness
Definition: Requirement.h:156
size_t hash() const noexcept override
std::ostream & describe(std::ostream &os) const override
virtual std::unique_ptr< ArbiterRequirement > intersect(const ArbiterRequirement &rhs) const =0
Attempts to create a requirement which expresses the intersection of this requirement and the given o...
bool satisfiedBy(const ArbiterSelectedVersion &selectedVersion) const override
Returns whether this requirement would be satisfied by using the given selected version.
std::unique_ptr< Base > clone() const override
Definition: Requirement.h:310
std::vector< std::shared_ptr< ArbiterRequirement > > _requirements
Definition: Requirement.h:275
Base class for objects that want to visit requirements.
Definition: Requirement.h:71
virtual bool satisfiedBy(const ArbiterSelectedVersion &selectedVersion) const =0
Returns whether this requirement would be satisfied by using the given selected version.
void visit(Visitor &visitor) const override
Visits the requirement, then any child requirements.
bool satisfiedBy(const ArbiterSelectedVersion &selectedVersion) const override
Returns whether this requirement would be satisfied by using the given selected version.
std::ostream & describe(std::ostream &os) const override
std::ostream & describe(std::ostream &os) const override
bool operator==(const Arbiter::Base &other) const override
bool satisfiedBy(const ArbiterSemanticVersion &version) const noexcept
void visit(Visitor &visitor) const override
Visits the requirement, then any child requirements.
std::unique_ptr< Base > clone() const override
Definition: Requirement.h:281
virtual std::unique_ptr< Base > clone() const =0
size_t hash() const
Definition: Value.h:96
size_t hash() const noexcept override
int priority() const noexcept override
Returns the priority of this requirement.
Definition: Requirement.h:315