use crate::error::{Error, ErrorKind};
use crate::internal::ConfigState;
use librpm_sys;
use std::ffi::{CStr, CString};
pub struct MacroContext(librpm_sys::rpmMacroContext);
impl Default for MacroContext {
fn default() -> MacroContext {
unsafe { MacroContext(librpm_sys::rpmGlobalMacroContext) }
}
}
impl MacroContext {
pub fn define(&self, macro_string: &str, level: isize) -> Result<(), Error> {
let cstr =
CString::new(macro_string).map_err(|e| format_err!(ErrorKind::InvalidArg, "{}", e))?;
let _lock = ConfigState::lock();
unsafe {
librpm_sys::rpmDefineMacro(self.0, cstr.as_ptr(), level as i32);
}
Ok(())
}
pub fn pop(&self, name: &str) -> Result<(), Error> {
let cstr = CString::new(name).map_err(|e| format_err!(ErrorKind::InvalidArg, "{}", e))?;
let _lock = ConfigState::lock();
unsafe {
librpm_sys::rpmPopMacro(self.0, cstr.as_ptr());
}
Ok(())
}
pub fn expand(&self, expr: &str) -> Result<String, Error> {
let cstr = CString::new(expr).map_err(|e| format_err!(ErrorKind::InvalidArg, "{}", e))?;
let _lock = ConfigState::lock();
let mut obuf: *mut std::os::raw::c_char = std::ptr::null_mut();
let rc = unsafe { librpm_sys::rpmExpandMacros(self.0, cstr.as_ptr(), &mut obuf, 0) };
if rc < 0 || obuf.is_null() {
if !obuf.is_null() {
unsafe { free(obuf.cast()) };
}
fail!(ErrorKind::Macro, "macro expansion failed: {}", expr);
}
let result = unsafe { CStr::from_ptr(obuf) }
.to_string_lossy()
.into_owned();
unsafe { free(obuf.cast()) };
Ok(result)
}
pub fn is_defined(&self, name: &str) -> bool {
let Ok(cstr) = CString::new(name) else {
return false;
};
let _lock = ConfigState::lock();
unsafe { librpm_sys::rpmMacroIsDefined(self.0, cstr.as_ptr()) != 0 }
}
}
pub fn expand_numeric(expr: &str) -> i32 {
let Ok(cstr) = CString::new(expr) else {
return 0;
};
let _lock = ConfigState::lock();
unsafe { librpm_sys::rpmExpandNumeric(cstr.as_ptr()) }
}
unsafe extern "C" {
fn free(ptr: *mut std::ffi::c_void);
}