use std::ffi::{CString, c_void};
use std::path::Path;
use std::ptr;
use crate::error::{VZError, VZResult};
use crate::shim_ffi;
fn path_cstring(path: &Path) -> VZResult<CString> {
CString::new(path.to_string_lossy().as_bytes()).map_err(|_| {
VZError::InvalidConfiguration(format!("path contains NUL: {}", path.display()))
})
}
unsafe fn take_bytes(bytes: *mut c_void, len: usize) -> Vec<u8> {
if bytes.is_null() {
return Vec::new();
}
unsafe {
let out = std::slice::from_raw_parts(bytes as *const u8, len).to_vec();
shim_ffi::abx_bytes_free(bytes);
out
}
}
pub struct MacHardwareModel {
inner: *mut c_void,
}
unsafe impl Send for MacHardwareModel {}
impl MacHardwareModel {
pub fn from_data(data: &[u8]) -> VZResult<Self> {
let obj = unsafe { shim_ffi::abx_mac_hw_model_from_data(data.as_ptr().cast(), data.len()) };
if obj.is_null() {
return Err(VZError::InvalidConfiguration(
"invalid macOS hardware model data representation".into(),
));
}
Ok(Self { inner: obj })
}
#[must_use]
pub fn is_supported(&self) -> bool {
unsafe { shim_ffi::abx_mac_hw_model_supported(self.inner.cast()) }
}
#[must_use]
pub fn data_representation(&self) -> Vec<u8> {
unsafe {
let mut len: usize = 0;
let bytes = shim_ffi::abx_mac_hw_model_data(self.inner.cast(), &raw mut len);
take_bytes(bytes, len)
}
}
pub(crate) fn from_owned_handle(handle: *mut c_void) -> Option<Self> {
if handle.is_null() {
return None;
}
Some(Self { inner: handle })
}
pub(crate) fn as_ptr(&self) -> *mut c_void {
self.inner
}
}
impl Drop for MacHardwareModel {
fn drop(&mut self) {
if !self.inner.is_null() {
unsafe { shim_ffi::abx_object_release(self.inner.cast()) };
}
}
}
pub struct MacMachineIdentifier {
inner: *mut c_void,
}
unsafe impl Send for MacMachineIdentifier {}
impl MacMachineIdentifier {
pub fn new() -> VZResult<Self> {
let obj = unsafe { shim_ffi::abx_mac_machine_id_new() };
Ok(Self { inner: obj })
}
pub fn from_data(data: &[u8]) -> VZResult<Self> {
let obj =
unsafe { shim_ffi::abx_mac_machine_id_from_data(data.as_ptr().cast(), data.len()) };
if obj.is_null() {
return Err(VZError::InvalidConfiguration(
"invalid macOS machine identifier data representation".into(),
));
}
Ok(Self { inner: obj })
}
#[must_use]
pub fn data_representation(&self) -> Vec<u8> {
unsafe {
let mut len: usize = 0;
let bytes = shim_ffi::abx_mac_machine_id_data(self.inner.cast(), &raw mut len);
take_bytes(bytes, len)
}
}
pub(crate) fn as_ptr(&self) -> *mut c_void {
self.inner
}
}
impl Drop for MacMachineIdentifier {
fn drop(&mut self) {
if !self.inner.is_null() {
unsafe { shim_ffi::abx_object_release(self.inner.cast()) };
}
}
}
pub struct MacAuxiliaryStorage {
inner: *mut c_void,
}
unsafe impl Send for MacAuxiliaryStorage {}
impl MacAuxiliaryStorage {
pub fn open(path: impl AsRef<Path>) -> VZResult<Self> {
let c_path = path_cstring(path.as_ref())?;
let obj = unsafe { shim_ffi::abx_aux_storage_open(c_path.as_ptr()) };
Ok(Self { inner: obj })
}
pub fn create(
path: impl AsRef<Path>,
hardware_model: &MacHardwareModel,
overwrite: bool,
) -> VZResult<Self> {
let c_path = path_cstring(path.as_ref())?;
unsafe {
let mut error: *mut std::ffi::c_char = ptr::null_mut();
let obj = shim_ffi::abx_aux_storage_create(
c_path.as_ptr(),
hardware_model.as_ptr().cast(),
overwrite,
&raw mut error,
);
if obj.is_null() {
return Err(VZError::OperationFailed(shim_ffi::take_error_string(error)));
}
Ok(Self { inner: obj })
}
}
pub(crate) fn as_ptr(&self) -> *mut c_void {
self.inner
}
}
impl Drop for MacAuxiliaryStorage {
fn drop(&mut self) {
if !self.inner.is_null() {
unsafe { shim_ffi::abx_object_release(self.inner.cast()) };
}
}
}