1//! Version compare module, with useful static comparison methods.
2
3use crate::version::Version;
4use crate::Cmp;
5
6/// Compare two version number strings to each other.
7///
8/// This compares version `a` to version `b`, and returns whether version `a` is greater, less
9/// or equal to version `b`.
10///
11/// If either version number string is invalid an error is returned.
12///
13/// One of the following operators is returned:
14///
15/// * `Cmp::Eq`
16/// * `Cmp::Lt`
17/// * `Cmp::Gt`
18///
19/// # Examples
20///
21/// ```
22/// use version_compare::{Cmp, compare};
23///
24/// assert_eq!(compare("1.2.3", "1.2.3"), Ok(Cmp::Eq));
25/// assert_eq!(compare("1.2.3", "1.2.4"), Ok(Cmp::Lt));
26/// assert_eq!(compare("1", "0.1"), Ok(Cmp::Gt));
27/// ```
28#[allow(clippy::result_unit_err)]
29pub fn compare<A, B>(a: A, b: B) -> Result<Cmp, ()>
30where
31 A: AsRef<str>,
32 B: AsRef<str>,
33{
34 let a: Version<'_> = Version::from(a.as_ref()).ok_or(())?;
35 let b: Version<'_> = Version::from(b.as_ref()).ok_or(())?;
36 Ok(a.compare(b))
37}
38
39/// Compare two version number strings to each other and test against the given comparison
40/// `operator`.
41///
42/// If either version number string is invalid an error is returned.
43///
44/// # Examples
45///
46/// ```
47/// use version_compare::{Cmp, compare_to};
48///
49/// assert!(compare_to("1.2.3", "1.2.3", Cmp::Eq).unwrap());
50/// assert!(compare_to("1.2.3", "1.2.3", Cmp::Le).unwrap());
51/// assert!(compare_to("1.2.3", "1.2.4", Cmp::Lt).unwrap());
52/// assert!(compare_to("1", "0.1", Cmp::Gt).unwrap());
53/// assert!(compare_to("1", "0.1", Cmp::Ge).unwrap());
54/// ```
55#[allow(clippy::result_unit_err)]
56pub fn compare_to<A, B>(a: A, b: B, operator: Cmp) -> Result<bool, ()>
57where
58 A: AsRef<str>,
59 B: AsRef<str>,
60{
61 let a: Version<'_> = Version::from(a.as_ref()).ok_or(())?;
62 let b: Version<'_> = Version::from(b.as_ref()).ok_or(())?;
63 Ok(a.compare_to(other:b, operator))
64}
65
66#[cfg_attr(tarpaulin, skip)]
67#[cfg(test)]
68mod tests {
69 use crate::test::{COMBIS, COMBIS_ERROR};
70 use crate::Cmp;
71
72 #[test]
73 fn compare() {
74 // Compare each version in the version set having the default manifest
75 for entry in COMBIS.iter().filter(|c| c.3.is_none()) {
76 assert_eq!(
77 super::compare(entry.0, entry.1),
78 Ok(entry.2),
79 "Testing that {} is {} {}",
80 entry.0,
81 entry.2.sign(),
82 entry.1,
83 );
84 }
85
86 // Compare each error version in the version set
87 for entry in COMBIS_ERROR {
88 let result = super::compare(entry.0, entry.1);
89
90 if result.is_ok() {
91 assert!(result != Ok(entry.2));
92 }
93 }
94 }
95
96 #[test]
97 fn compare_to() {
98 // Compare each version in the version set having the default manifest
99 for entry in COMBIS.iter().filter(|c| c.3.is_none()) {
100 // Test
101 assert!(super::compare_to(entry.0, entry.1, entry.2).unwrap());
102
103 // Make sure the inverse operator is not correct
104 assert!(!super::compare_to(entry.0, entry.1, entry.2.invert()).unwrap());
105 }
106
107 // Compare each error version in the version set
108 for entry in COMBIS_ERROR {
109 let result = super::compare_to(entry.0, entry.1, entry.2);
110
111 if result.is_ok() {
112 assert!(!result.unwrap())
113 }
114 }
115
116 // Assert an exceptional case, compare to not equal
117 assert!(super::compare_to("1.2.3", "1.2", Cmp::Ne).unwrap());
118 }
119}
120