use {
crate::{error::result_from_raw, sys},
std::sync::{Mutex, MutexGuard},
};
fn lock_counter<'a>() -> MutexGuard<'a, usize> {
static LOCKED_COUNTER: Mutex<usize> = Mutex::new(0);
match LOCKED_COUNTER.lock() {
Ok(lock) => lock,
Err(poison) => {
LOCKED_COUNTER.clear_poison();
poison.into_inner()
}
}
}
pub struct WimLib {
_private: (),
}
impl Clone for WimLib {
fn clone(&self) -> Self {
*lock_counter() += 1;
Self { _private: () }
}
}
impl Drop for WimLib {
fn drop(&mut self) {
let mut counter_lock = lock_counter();
*counter_lock -= 1;
if *counter_lock == 0 {
unsafe { sys::wimlib_global_cleanup() };
}
}
}
impl Default for WimLib {
fn default() -> Self {
let mut counter_lock = lock_counter();
if *counter_lock == 0 {
let stat = unsafe { sys::wimlib_global_init(InitFlags::empty().bits()) };
assert_eq!(
stat, 0,
"initialising wimlib with empty flags should always return zero"
)
}
*counter_lock += 1;
Self { _private: () }
}
}
impl WimLib {
pub fn try_init(flags: InitFlags) -> Result<Self, TryInitError> {
let mut counter_lock = lock_counter();
if *counter_lock == 0 {
return Err(TryInitError::AlreadyInitialised);
}
let stat = unsafe { sys::wimlib_global_init(flags.bits()) };
result_from_raw(stat).map_err(TryInitError::Wimlib)?;
*counter_lock += 1;
Ok(Self { _private: () })
}
}
pub enum TryInitError {
AlreadyInitialised,
Wimlib(crate::Error),
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct InitFlags: std::ffi::c_int {
#[cfg(any(windows, doc))]
const DONT_ACQUIRE_PRIVILEGES = sys::WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES as _;
#[cfg(any(windows, doc))]
const STRICT_CAPTURE_PRIVILEGES = sys::WIMLIB_INIT_FLAG_STRICT_CAPTURE_PRIVILEGES as _;
#[cfg(any(windows, doc))]
const STRICT_APPLY_PRIVILEGES = sys::WIMLIB_INIT_FLAG_STRICT_APPLY_PRIVILEGES as _;
const DEFAULT_CASE_SENSITIVE = sys::WIMLIB_INIT_FLAG_DEFAULT_CASE_SENSITIVE as _;
const DEFAULT_CASE_INSENSITIVE = sys::WIMLIB_INIT_FLAG_DEFAULT_CASE_INSENSITIVE as _;
}
}