1#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case)]
16#![allow(clippy::missing_safety_doc)]
17
18#[cfg(not(feature = "bindgen"))]
20#[allow(clippy::all)]
21mod ffi {
22 include!("bindings/prebuilt.rs");
23}
24
25#[cfg(feature = "bindgen")]
27#[allow(clippy::all)]
28mod ffi {
29 include!(concat!(env!("OUT_DIR"), "/binding.rs"));
30}
31
32pub use ffi::*;
33
34#[cfg(feature = "helpers")]
36pub mod helpers {
37 use super::*;
38 use std::ffi::CString;
39 use std::sync::OnceLock;
40
41 pub fn init(argv0: &str) -> Result<(), i32> {
43 static INIT: OnceLock<Result<(), i32>> = OnceLock::new();
44 if let Some(res) = INIT.get() {
46 return *res;
47 }
48 let c = CString::new(argv0).map_err(|_| -1)?;
49 *INIT.get_or_init(|| {
50 let rc = unsafe { vips_init(c.as_ptr()) };
51 if rc == 0 { Ok(()) } else { Err(rc) }
52 })
53 }
54
55 pub fn shutdown() {
57 unsafe { vips_shutdown() }
58 }
59
60 pub fn version() -> (i32, i32, i32) {
62 static VER: OnceLock<(i32, i32, i32)> = OnceLock::new();
63 *VER.get_or_init(|| unsafe { (vips_version(0), vips_version(1), vips_version(2)) })
64 }
65
66 pub fn version_string() -> &'static str {
71 static STR: OnceLock<&'static str> = OnceLock::new();
72 STR.get_or_init(|| unsafe {
74 let p = vips_version_string();
75 if p.is_null() {
76 ""
77 } else {
78 std::ffi::CStr::from_ptr(p).to_str().unwrap_or("")
79 }
80 })
81 }
82}
83
84#[cfg(all(test, feature = "helpers"))]
85mod tests {
86 use super::helpers;
87
88 #[test]
89 fn init_and_version() {
90 helpers::init("vips-sys-test").expect("vips_init");
91 let (maj, min, mic) = helpers::version();
92 assert!(maj >= 0 && min >= 0 && mic >= 0);
93 assert!(!helpers::version_string().is_empty());
94 assert_eq!(helpers::version(), (maj, min, mic));
96 }
97}