1#![allow(non_upper_case_globals)]
14#![allow(non_camel_case_types)]
15#![allow(non_snake_case)]
16
17pub mod ffi {
19 include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
20}
21
22pub use ffi::{
23 VERSIONFLAG_ANY_IS_PATCH, VERSIONFLAG_LOWER_BOUND, VERSIONFLAG_P_IS_PATCH,
24 VERSIONFLAG_UPPER_BOUND, version_compare2, version_compare4,
25};
26
27use std::cmp::Ordering;
28use std::ffi::CString;
29
30pub fn compare(v1: &str, v2: &str) -> Ordering {
46 let v1 = CString::new(v1).expect("v1 contains interior null byte");
47 let v2 = CString::new(v2).expect("v2 contains interior null byte");
48 let result = unsafe { ffi::version_compare2(v1.as_ptr(), v2.as_ptr()) };
49 result.cmp(&0)
50}
51
52pub fn compare_with_flags(v1: &str, v2: &str, v1_flags: u32, v2_flags: u32) -> Ordering {
74 let v1 = CString::new(v1).expect("v1 contains interior null byte");
75 let v2 = CString::new(v2).expect("v2 contains interior null byte");
76 let result = unsafe {
77 ffi::version_compare4(v1.as_ptr(), v2.as_ptr(), v1_flags as i32, v2_flags as i32)
78 };
79 result.cmp(&0)
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn basic_comparison() {
88 assert_eq!(compare("0.99", "1.11"), Ordering::Less);
89 assert_eq!(compare("1.0", "1.0.0"), Ordering::Equal);
90 assert_eq!(compare("1.0", "0.99"), Ordering::Greater);
91 }
92
93 #[test]
94 fn prerelease() {
95 assert_eq!(compare("1.0alpha1", "1.0"), Ordering::Less);
96 assert_eq!(compare("1.0alpha1", "1.0rc1"), Ordering::Less);
97 assert_eq!(compare("1.0rc1", "1.0"), Ordering::Less);
98 }
99
100 #[test]
101 fn postrelease() {
102 assert_eq!(compare("1.0patch1", "1.0"), Ordering::Greater);
103 assert_eq!(compare("1.0.1", "1.0"), Ordering::Greater);
104 }
105
106 #[test]
107 fn p_is_patch_flag() {
108 assert_eq!(compare("1.0p1", "1.0"), Ordering::Less);
110
111 assert_eq!(
113 compare_with_flags("1.0p1", "1.0", VERSIONFLAG_P_IS_PATCH, 0),
114 Ordering::Greater,
115 );
116 }
117
118 #[test]
119 fn ffi_direct() {
120 let v1 = CString::new("1.0").unwrap();
121 let v2 = CString::new("2.0").unwrap();
122 let result = unsafe { ffi::version_compare2(v1.as_ptr(), v2.as_ptr()) };
123 assert_eq!(result, -1);
124 }
125}