use crate::{Error, Result, take_vips_error};
use std::ffi::CString;
use std::sync::{Mutex, OnceLock};
static VIPS: OnceLock<InitGuard> = OnceLock::new();
static INIT_LOCK: Mutex<()> = Mutex::new(());
pub(crate) struct InitGuard;
impl Drop for InitGuard {
fn drop(&mut self) {
unsafe {
vips_sys::vips_shutdown();
}
}
}
pub fn init(app_name: Option<&str>) -> Result<()> {
if VIPS.get().is_some() {
return Ok(());
}
let _guard = INIT_LOCK.lock().unwrap_or_else(|e| e.into_inner());
if VIPS.get().is_some() {
return Ok(());
}
let cstr = CString::new(app_name.unwrap_or("vips-rs"))
.map_err(|e| Error::InitFailed(format!("invalid app name: {e}")))?;
let rc = unsafe { vips_sys::vips_init(cstr.as_ptr()) };
if rc != 0 {
let msg = take_vips_error().unwrap_or_else(|| "vips_init() failed".to_string());
return Err(Error::InitFailed(msg));
}
let _ = VIPS.set(InitGuard);
Ok(())
}
#[inline]
pub fn is_initialized() -> bool {
VIPS.get().is_some()
}