use std::ffi::c_void;
use std::path::Path;
use objc2::runtime::AnyObject;
use crate::error::{VZError, VZResult};
use crate::ffi::{
extract_nserror, get_class, nsdata_from_bytes, nsdata_to_vec, nsurl_file_path, release, retain,
};
use crate::{msg_send, msg_send_bool};
pub struct MacHardwareModel {
inner: *mut AnyObject,
}
unsafe impl Send for MacHardwareModel {}
impl MacHardwareModel {
pub fn from_data(data: &[u8]) -> VZResult<Self> {
unsafe {
let cls = get_class("VZMacHardwareModel").ok_or_else(|| VZError::Internal {
code: -1,
message: "VZMacHardwareModel class not found".into(),
})?;
let nsdata = nsdata_from_bytes(data);
let alloc = msg_send!(cls, alloc);
let obj = msg_send!(alloc, initWithDataRepresentation: nsdata);
release(nsdata);
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 { msg_send_bool!(self.inner, isSupported).as_bool() }
}
#[must_use]
pub fn data_representation(&self) -> Vec<u8> {
let data = unsafe { msg_send!(self.inner, dataRepresentation) };
nsdata_to_vec(data)
}
pub(crate) fn from_retained_ptr(ptr: *mut AnyObject) -> Option<Self> {
if ptr.is_null() {
return None;
}
Some(Self { inner: retain(ptr) })
}
pub(crate) fn as_ptr(&self) -> *mut AnyObject {
self.inner
}
}
impl Drop for MacHardwareModel {
fn drop(&mut self) {
if !self.inner.is_null() {
release(self.inner);
}
}
}
pub struct MacMachineIdentifier {
inner: *mut AnyObject,
}
unsafe impl Send for MacMachineIdentifier {}
impl MacMachineIdentifier {
pub fn new() -> VZResult<Self> {
unsafe {
let cls = get_class("VZMacMachineIdentifier").ok_or_else(|| VZError::Internal {
code: -1,
message: "VZMacMachineIdentifier class not found".into(),
})?;
let alloc = msg_send!(cls, alloc);
let obj = msg_send!(alloc, init);
if obj.is_null() {
return Err(VZError::Internal {
code: -1,
message: "Failed to create VZMacMachineIdentifier".into(),
});
}
Ok(Self { inner: obj })
}
}
pub fn from_data(data: &[u8]) -> VZResult<Self> {
unsafe {
let cls = get_class("VZMacMachineIdentifier").ok_or_else(|| VZError::Internal {
code: -1,
message: "VZMacMachineIdentifier class not found".into(),
})?;
let nsdata = nsdata_from_bytes(data);
let alloc = msg_send!(cls, alloc);
let obj = msg_send!(alloc, initWithDataRepresentation: nsdata);
release(nsdata);
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> {
let data = unsafe { msg_send!(self.inner, dataRepresentation) };
nsdata_to_vec(data)
}
pub(crate) fn as_ptr(&self) -> *mut AnyObject {
self.inner
}
}
impl Drop for MacMachineIdentifier {
fn drop(&mut self) {
if !self.inner.is_null() {
release(self.inner);
}
}
}
pub struct MacAuxiliaryStorage {
inner: *mut AnyObject,
}
unsafe impl Send for MacAuxiliaryStorage {}
impl MacAuxiliaryStorage {
pub fn open(path: impl AsRef<Path>) -> VZResult<Self> {
let path_str = path.as_ref().to_string_lossy();
unsafe {
let cls = get_class("VZMacAuxiliaryStorage").ok_or_else(|| VZError::Internal {
code: -1,
message: "VZMacAuxiliaryStorage class not found".into(),
})?;
let url = nsurl_file_path(&path_str);
let alloc = msg_send!(cls, alloc);
let obj = msg_send!(alloc, initWithURL: url);
release(url);
if obj.is_null() {
return Err(VZError::InvalidConfiguration(format!(
"failed to open macOS auxiliary storage: {path_str}"
)));
}
Ok(Self { inner: obj })
}
}
pub fn create(
path: impl AsRef<Path>,
hardware_model: &MacHardwareModel,
overwrite: bool,
) -> VZResult<Self> {
let path_str = path.as_ref().to_string_lossy();
unsafe {
let cls = get_class("VZMacAuxiliaryStorage").ok_or_else(|| VZError::Internal {
code: -1,
message: "VZMacAuxiliaryStorage class not found".into(),
})?;
let url = nsurl_file_path(&path_str);
let alloc = msg_send!(cls, alloc);
let options: u64 = u64::from(overwrite);
let mut error: *mut AnyObject = std::ptr::null_mut();
let sel = objc2::sel!(initCreatingStorageAtURL:hardwareModel:options:error:);
let func: unsafe extern "C" fn(
*mut AnyObject,
objc2::runtime::Sel,
*const AnyObject,
*const AnyObject,
u64,
*mut *mut AnyObject,
) -> *mut AnyObject =
std::mem::transmute(crate::ffi::runtime::objc_msgSend as *const c_void);
let obj = func(
alloc,
sel,
url as *const AnyObject,
hardware_model.as_ptr() as *const AnyObject,
options,
&mut error,
);
release(url);
if obj.is_null() {
return Err(extract_nserror(error));
}
Ok(Self { inner: obj })
}
}
pub(crate) fn as_ptr(&self) -> *mut AnyObject {
self.inner
}
}
impl Drop for MacAuxiliaryStorage {
fn drop(&mut self) {
if !self.inner.is_null() {
release(self.inner);
}
}
}