pubgrub/
version_set.rs

1// SPDX-License-Identifier: MPL-2.0
2
3use std::fmt::{Debug, Display};
4
5use crate::Ranges;
6
7/// A set of versions.
8///
9/// See [`Ranges`] for an implementation.
10///
11/// The methods with default implementations can be overwritten for better performance, but their
12/// output must be equal to the default implementation.
13///
14/// # Equality
15///
16/// It is important that the `Eq` trait is implemented so that if two sets contain the same
17/// versions, they are equal under `Eq`. In particular, you can only use `#[derive(Eq, PartialEq)]`
18/// if `Eq` is strictly equivalent to the structural equality, i.e. if version sets are always
19/// stored in a canonical representations. Such problems may arise if your implementations of
20/// `complement()` and `intersection()` do not return canonical representations.
21///
22/// For example, `>=1,<4 || >=2,<5` and `>=1,<4 || >=3,<5` are equal, because they can both be
23/// normalized to `>=1,<5`.
24///
25/// Note that pubgrub does not know which versions actually exist for a package, the contract
26/// is about upholding the mathematical properties of set operations, assuming all versions are
27/// possible. This is required for the solver to determine the relationship of version sets to each
28/// other.
29pub trait VersionSet: Debug + Display + Clone + Eq {
30    /// Version type associated with the sets manipulated.
31    type V: Debug + Display + Clone + Ord;
32
33    // Constructors
34
35    /// An empty set containing no version.
36    fn empty() -> Self;
37
38    /// A set containing only the given version.
39    fn singleton(v: Self::V) -> Self;
40
41    // Operations
42
43    /// The set of all version that are not in this set.
44    fn complement(&self) -> Self;
45
46    /// The set of all versions that are in both sets.
47    fn intersection(&self, other: &Self) -> Self;
48
49    /// Whether the version is part of this set.
50    fn contains(&self, v: &Self::V) -> bool;
51
52    // Automatically implemented functions
53
54    /// The set containing all versions.
55    ///
56    /// The default implementation is the complement of the empty set.
57    fn full() -> Self {
58        Self::empty().complement()
59    }
60
61    /// The set of all versions that are either (or both) of the sets.
62    ///
63    /// The default implementation is complement of the intersection of the complements of both sets
64    /// (De Morgan's law).
65    fn union(&self, other: &Self) -> Self {
66        self.complement()
67            .intersection(&other.complement())
68            .complement()
69    }
70
71    /// Whether the ranges have no overlapping segments.
72    fn is_disjoint(&self, other: &Self) -> bool {
73        self.intersection(other) == Self::empty()
74    }
75
76    /// Whether all ranges of `self` are contained in `other`.
77    fn subset_of(&self, other: &Self) -> bool {
78        self == &self.intersection(other)
79    }
80}
81
82/// [`Ranges`] contains optimized implementations of all operations.
83impl<T: Debug + Display + Clone + Eq + Ord> VersionSet for Ranges<T> {
84    type V = T;
85
86    fn empty() -> Self {
87        Ranges::empty()
88    }
89
90    fn singleton(v: Self::V) -> Self {
91        Ranges::singleton(v)
92    }
93
94    fn complement(&self) -> Self {
95        Ranges::complement(self)
96    }
97
98    fn intersection(&self, other: &Self) -> Self {
99        Ranges::intersection(self, other)
100    }
101
102    fn contains(&self, v: &Self::V) -> bool {
103        Ranges::contains(self, v)
104    }
105
106    fn full() -> Self {
107        Ranges::full()
108    }
109
110    fn union(&self, other: &Self) -> Self {
111        Ranges::union(self, other)
112    }
113
114    fn is_disjoint(&self, other: &Self) -> bool {
115        Ranges::is_disjoint(self, other)
116    }
117
118    fn subset_of(&self, other: &Self) -> bool {
119        Ranges::subset_of(self, other)
120    }
121}