use crate::error::{VZError, VZResult};
use crate::ffi::{get_class, release};
use crate::{msg_send, msg_send_bool, msg_send_void_bool};
use objc2::runtime::{AnyObject, Bool};
pub trait Platform {
fn as_ptr(&self) -> *mut AnyObject;
}
pub struct GenericPlatform {
inner: *mut AnyObject,
}
unsafe impl Send for GenericPlatform {}
impl GenericPlatform {
pub fn new() -> VZResult<Self> {
unsafe {
let cls =
get_class("VZGenericPlatformConfiguration").ok_or_else(|| VZError::Internal {
code: -1,
message: "VZGenericPlatformConfiguration class not found".into(),
})?;
let obj = msg_send!(cls, new);
if obj.is_null() {
return Err(VZError::Internal {
code: -1,
message: "Failed to create generic platform".into(),
});
}
let _: *mut AnyObject = msg_send!(obj, retain);
Ok(Self { inner: obj })
}
}
pub fn is_nested_virt_supported() -> bool {
let Some(cls) = get_class("VZGenericPlatformConfiguration") else {
return false;
};
let sel = objc2::sel!(isNestedVirtualizationSupported);
if cls.class_method(sel).is_none() {
return false;
}
unsafe { msg_send_bool!(cls, isNestedVirtualizationSupported).as_bool() }
}
pub fn set_nested_virt_enabled(&self, enabled: bool) {
let sel = objc2::sel!(setNestedVirtualizationEnabled:);
if !unsafe { &*(self.inner as *const AnyObject) }
.class()
.responds_to(sel)
{
return;
}
unsafe {
msg_send_void_bool!(self.inner, setNestedVirtualizationEnabled: Bool::new(enabled));
}
}
}
impl Default for GenericPlatform {
fn default() -> Self {
Self::new().expect("Failed to create generic platform")
}
}
impl Platform for GenericPlatform {
fn as_ptr(&self) -> *mut AnyObject {
self.inner
}
}
impl Drop for GenericPlatform {
fn drop(&mut self) {
if !self.inner.is_null() {
release(self.inner);
}
}
}