#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case)]
#![allow(clippy::missing_safety_doc)]
#[cfg(not(feature = "bindgen"))]
#[allow(clippy::all)]
mod ffi {
include!("bindings/prebuilt.rs");
}
#[cfg(feature = "bindgen")]
#[allow(clippy::all)]
mod ffi {
include!(concat!(env!("OUT_DIR"), "/binding.rs"));
}
pub use ffi::*;
const _: () = {
assert!(core::mem::size_of::<gsize>() == core::mem::size_of::<usize>());
assert!(core::mem::size_of::<gssize>() == core::mem::size_of::<isize>());
assert!(core::mem::size_of::<GType>() == core::mem::size_of::<usize>());
};
#[cfg(feature = "helpers")]
pub mod helpers {
use super::*;
use std::ffi::CString;
use std::sync::{Mutex, OnceLock};
static INIT: OnceLock<()> = OnceLock::new();
static INIT_LOCK: Mutex<()> = Mutex::new(());
pub fn is_initialized() -> bool {
INIT.get().is_some()
}
pub fn init(argv0: &str) -> Result<(), i32> {
if INIT.get().is_some() {
return Ok(());
}
let _guard = INIT_LOCK.lock().unwrap_or_else(|e| e.into_inner());
if INIT.get().is_some() {
return Ok(());
}
let c = CString::new(argv0).map_err(|_| -1)?;
let rc = unsafe { vips_init(c.as_ptr()) };
if rc != 0 {
return Err(rc);
}
let _ = INIT.set(());
Ok(())
}
pub unsafe fn shutdown() {
unsafe { vips_shutdown() }
}
pub fn version() -> (i32, i32, i32) {
static VER: OnceLock<(i32, i32, i32)> = OnceLock::new();
*VER.get_or_init(|| unsafe { (vips_version(0), vips_version(1), vips_version(2)) })
}
pub fn version_string() -> &'static str {
static STR: OnceLock<&'static str> = OnceLock::new();
STR.get_or_init(|| unsafe {
let p = vips_version_string();
if p.is_null() {
""
} else {
std::ffi::CStr::from_ptr(p).to_str().unwrap_or("")
}
})
}
}
#[cfg(all(test, feature = "helpers"))]
mod tests {
use super::helpers;
#[test]
fn init_and_version() {
assert_eq!(helpers::init("invalid\0name"), Err(-1));
helpers::init("vips-sys-test").expect("vips_init");
let (maj, min, mic) = helpers::version();
assert!(maj >= 0 && min >= 0 && mic >= 0);
assert!(!helpers::version_string().is_empty());
assert_eq!(helpers::version(), (maj, min, mic));
std::thread::scope(|scope| {
for _ in 0..8 {
scope.spawn(|| helpers::init("parallel-init").unwrap());
}
});
}
}