use crate::error::{VZError, VZResult};
use crate::ffi::get_class;
use crate::{msg_send, msg_send_u64, msg_send_void_u64};
use objc2::runtime::AnyObject;
pub struct MemoryBalloonDeviceConfiguration {
inner: *mut AnyObject,
}
unsafe impl Send for MemoryBalloonDeviceConfiguration {}
impl MemoryBalloonDeviceConfiguration {
pub fn new() -> VZResult<Self> {
unsafe {
let cls = get_class("VZVirtioTraditionalMemoryBalloonDeviceConfiguration").ok_or_else(
|| VZError::Internal {
code: -1,
message: "VZVirtioTraditionalMemoryBalloonDeviceConfiguration not found".into(),
},
)?;
let obj = msg_send!(cls, new);
if obj.is_null() {
return Err(VZError::Internal {
code: -1,
message: "Failed to create balloon device configuration".into(),
});
}
let _: *mut AnyObject = msg_send!(obj, retain);
Ok(Self { inner: obj })
}
}
#[must_use]
pub fn into_ptr(self) -> *mut AnyObject {
let ptr = self.inner;
std::mem::forget(self);
ptr
}
}
impl Default for MemoryBalloonDeviceConfiguration {
fn default() -> Self {
Self::new().expect("Failed to create balloon device configuration")
}
}
impl Drop for MemoryBalloonDeviceConfiguration {
fn drop(&mut self) {
if !self.inner.is_null() {
crate::ffi::release(self.inner);
}
}
}
pub struct MemoryBalloonDevice {
inner: *mut AnyObject,
}
unsafe impl Send for MemoryBalloonDevice {}
unsafe impl Sync for MemoryBalloonDevice {}
impl MemoryBalloonDevice {
pub(crate) fn from_raw(ptr: *mut AnyObject) -> Self {
Self { inner: ptr }
}
pub fn set_target_memory_size(&self, bytes: u64) {
if self.inner.is_null() {
tracing::warn!("set_target_memory_size called on null device");
return;
}
unsafe {
msg_send_void_u64!(self.inner, setTargetVirtualMachineMemorySize: bytes);
}
tracing::debug!(
"Set balloon target memory to {} bytes ({}MB)",
bytes,
bytes / (1024 * 1024)
);
}
pub fn target_memory_size(&self) -> u64 {
if self.inner.is_null() {
tracing::warn!("target_memory_size called on null device");
return 0;
}
unsafe { msg_send_u64!(self.inner, targetVirtualMachineMemorySize) }
}
#[must_use]
pub fn as_ptr(&self) -> *mut AnyObject {
self.inner
}
}
pub fn vm_memory_balloon_devices(vm_ptr: *mut AnyObject) -> Vec<MemoryBalloonDevice> {
if vm_ptr.is_null() {
return Vec::new();
}
unsafe {
let devices: *mut AnyObject = msg_send!(vm_ptr, memoryBalloonDevices);
if devices.is_null() {
return Vec::new();
}
let count = crate::ffi::nsarray_count(devices);
let mut result = Vec::with_capacity(count);
for i in 0..count {
let device = crate::ffi::nsarray_object_at_index(devices, i);
if !device.is_null() {
result.push(MemoryBalloonDevice::from_raw(device));
}
}
result
}
}