1 //! Version compare module, with useful static comparison methods.
2 //!
3 //! This module provides the `VersionCompare` struct, which provides many static functions, that are
4 //! useful for version comparison.
5 
6 use crate::comp_op::CompOp;
7 use crate::version::Version;
8 
9 /// The main library structure, which provides various static methods for easy version comparison.
10 ///
11 /// This structure uses static methods only, and doesn't need to be constructed.
12 pub struct VersionCompare {}
13 
14 impl VersionCompare {
15     /// Compare two version number strings to each other.
16     /// This compares version `a` to version `b`, and returns whether version `a` is greater, less
17     /// or equal to version `b`.
18     ///
19     /// The two given version numbers must be valid, or an error will be returned.
20     ///
21     /// One of the following ok results may be returned:
22     ///
23     /// * `CompOp::Eq`
24     /// * `CompOp::Lt`
25     /// * `CompOp::Gt`
26     ///
27     /// # Examples
28     ///
29     /// ```
30     /// use version_compare::{CompOp, VersionCompare};
31     ///
32     /// // Compare version numbers
33     /// assert_eq!(VersionCompare::compare("1.2.3", "1.2.3"), Ok(CompOp::Eq));
34     /// assert_eq!(VersionCompare::compare("1.2.3", "1.2.4"), Ok(CompOp::Lt));
35     /// assert_eq!(VersionCompare::compare("1", "0.1"), Ok(CompOp::Gt));
36     /// ```
compare(a: &str, b: &str) -> Result<CompOp, ()>37     pub fn compare(a: &str, b: &str) -> Result<CompOp, ()> {
38         // Create version instances
39         let a_ver = Version::from(a);
40         let b_ver = Version::from(b);
41 
42         // Both version numbers must have been parsed
43         if a_ver.is_none() || b_ver.is_none() {
44             return Err(());
45         }
46 
47         // Compare and return the result
48         Ok(a_ver.unwrap().compare(&b_ver.unwrap()))
49     }
50 
51     /// Compare two version number strings to each other and check whether the given comparison
52     /// `operator` is valid.
53     ///
54     /// The two given version numbers must be valid, or an error will be returned.
55     ///
56     /// # Examples
57     ///
58     /// ```
59     /// use version_compare::{CompOp, VersionCompare};
60     ///
61     /// // Compare version numbers
62     /// assert!(VersionCompare::compare_to("1.2.3", "1.2.3", &CompOp::Eq).unwrap());
63     /// assert!(VersionCompare::compare_to("1.2.3", "1.2.3", &CompOp::Le).unwrap());
64     /// assert!(VersionCompare::compare_to("1.2.3", "1.2.4", &CompOp::Lt).unwrap());
65     /// assert!(VersionCompare::compare_to("1", "0.1", &CompOp::Gt).unwrap());
66     /// assert!(VersionCompare::compare_to("1", "0.1", &CompOp::Ge).unwrap());
67     /// ```
compare_to(a: &str, b: &str, operator: &CompOp) -> Result<bool, ()>68     pub fn compare_to(a: &str, b: &str, operator: &CompOp) -> Result<bool, ()> {
69         // Create version instances
70         let a_ver = Version::from(a);
71         let b_ver = Version::from(b);
72 
73         // Both version numbers must have been parsed
74         if a_ver.is_none() || b_ver.is_none() {
75             return Err(());
76         }
77 
78         // Compare and return the result
79         Ok(a_ver.unwrap().compare_to(&b_ver.unwrap(), &operator))
80     }
81 }
82 
83 #[cfg_attr(tarpaulin, skip)]
84 #[cfg(test)]
85 mod tests {
86     use crate::comp_op::CompOp;
87     use crate::test::test_version_set::{TEST_VERSION_SETS, TEST_VERSION_SETS_ERROR};
88 
89     use super::VersionCompare;
90 
91     #[test]
compare()92     fn compare() {
93         // Compare each version in the version set
94         for entry in TEST_VERSION_SETS {
95             assert_eq!(
96                 VersionCompare::compare(&entry.0, &entry.1),
97                 Ok(entry.2.clone()),
98                 "Testing that {} is {} {}", &entry.0, &entry.2.sign(), &entry.1
99             );
100         }
101 
102         // Compare each error version in the version set
103         for entry in TEST_VERSION_SETS_ERROR {
104             let result = VersionCompare::compare(&entry.0, &entry.1);
105 
106             if result.is_ok() {
107                 assert!(result != Ok(entry.2.clone()));
108             }
109         }
110     }
111 
112     #[test]
compare_to()113     fn compare_to() {
114         // Compare each version in the version set
115         for entry in TEST_VERSION_SETS {
116             // Test
117             assert!(VersionCompare::compare_to(&entry.0, &entry.1, &entry.2).unwrap());
118 
119             // Make sure the inverse operator is not correct
120             assert_eq!(
121                 VersionCompare::compare_to(&entry.0, &entry.1, &entry.2.invert()).unwrap(),
122                 false
123             );
124         }
125 
126         // Compare each error version in the version set
127         for entry in TEST_VERSION_SETS_ERROR {
128             let result = VersionCompare::compare_to(&entry.0, &entry.1, &entry.2);
129 
130             if result.is_ok() {
131                 assert!(!result.unwrap())
132             }
133         }
134 
135         // Assert an exceptional case, compare to not equal
136         assert!(VersionCompare::compare_to("1.2.3", "1.2", &CompOp::Ne).unwrap());
137     }
138 }
139