#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
pub mod ffi {
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
pub use ffi::{
VERSIONFLAG_ANY_IS_PATCH, VERSIONFLAG_LOWER_BOUND, VERSIONFLAG_P_IS_PATCH,
VERSIONFLAG_UPPER_BOUND, version_compare2, version_compare4,
};
use std::cmp::Ordering;
use std::ffi::CString;
pub fn compare(v1: &str, v2: &str) -> Ordering {
let v1 = CString::new(v1).expect("v1 contains interior null byte");
let v2 = CString::new(v2).expect("v2 contains interior null byte");
let result = unsafe { ffi::version_compare2(v1.as_ptr(), v2.as_ptr()) };
result.cmp(&0)
}
pub fn compare_with_flags(v1: &str, v2: &str, v1_flags: u32, v2_flags: u32) -> Ordering {
let v1 = CString::new(v1).expect("v1 contains interior null byte");
let v2 = CString::new(v2).expect("v2 contains interior null byte");
let result = unsafe {
ffi::version_compare4(v1.as_ptr(), v2.as_ptr(), v1_flags as i32, v2_flags as i32)
};
result.cmp(&0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic_comparison() {
assert_eq!(compare("0.99", "1.11"), Ordering::Less);
assert_eq!(compare("1.0", "1.0.0"), Ordering::Equal);
assert_eq!(compare("1.0", "0.99"), Ordering::Greater);
}
#[test]
fn prerelease() {
assert_eq!(compare("1.0alpha1", "1.0"), Ordering::Less);
assert_eq!(compare("1.0alpha1", "1.0rc1"), Ordering::Less);
assert_eq!(compare("1.0rc1", "1.0"), Ordering::Less);
}
#[test]
fn postrelease() {
assert_eq!(compare("1.0patch1", "1.0"), Ordering::Greater);
assert_eq!(compare("1.0.1", "1.0"), Ordering::Greater);
}
#[test]
fn p_is_patch_flag() {
assert_eq!(compare("1.0p1", "1.0"), Ordering::Less);
assert_eq!(
compare_with_flags("1.0p1", "1.0", VERSIONFLAG_P_IS_PATCH, 0),
Ordering::Greater,
);
}
#[test]
fn ffi_direct() {
let v1 = CString::new("1.0").unwrap();
let v2 = CString::new("2.0").unwrap();
let result = unsafe { ffi::version_compare2(v1.as_ptr(), v2.as_ptr()) };
assert_eq!(result, -1);
}
}