use crate::{
base::{Id, NSArray, NSError},
virtualization::boot_loader::VZBootLoader,
virtualization::entropy_device::VZEntropyDeviceConfiguration,
virtualization::memory_device::VZMemoryBalloonDeviceConfiguration,
virtualization::network_device::VZNetworkDeviceConfiguration,
virtualization::serial_port::VZSerialPortConfiguration,
virtualization::socket_device::VZSocketDeviceConfiguration,
virtualization::storage_device::VZStorageDeviceConfiguration,
};
use block::Block;
use objc::runtime::BOOL;
use objc::{class, msg_send, sel, sel_impl};
use objc::{rc::StrongPtr, runtime::YES};
pub struct VZVirtualMachineConfigurationBuilder {
conf: VZVirtualMachineConfiguration,
}
impl VZVirtualMachineConfigurationBuilder {
pub fn new() -> Self {
VZVirtualMachineConfigurationBuilder {
conf: VZVirtualMachineConfiguration::new(),
}
}
pub fn boot_loader<T: VZBootLoader>(mut self, boot_loader: T) -> Self {
self.conf.set_boot_loader(boot_loader);
self
}
pub fn cpu_count(mut self, cpu_count: usize) -> Self {
self.conf.set_cpu_count(cpu_count);
self
}
pub fn memory_size(mut self, memory_size: usize) -> Self {
self.conf.set_memory_size(memory_size);
self
}
pub fn entropy_devices<T: VZEntropyDeviceConfiguration>(
mut self,
entropy_devices: Vec<T>,
) -> Self {
self.conf.set_entropy_devices(entropy_devices);
self
}
pub fn memory_balloon_devices<T: VZMemoryBalloonDeviceConfiguration>(
mut self,
memory_balloon_devices: Vec<T>,
) -> Self {
self.conf.set_memory_balloon_devices(memory_balloon_devices);
self
}
pub fn network_devices<T: VZNetworkDeviceConfiguration>(
mut self,
network_devices: Vec<T>,
) -> Self {
self.conf.set_network_devices(network_devices);
self
}
pub fn serial_ports<T: VZSerialPortConfiguration>(mut self, serial_ports: Vec<T>) -> Self {
self.conf.set_serial_ports(serial_ports);
self
}
pub fn socket_devices<T: VZSocketDeviceConfiguration>(
mut self,
socket_devices: Vec<T>,
) -> Self {
self.conf.set_socket_devices(socket_devices);
self
}
pub fn storage_devices<T: VZStorageDeviceConfiguration>(
mut self,
storage_devices: Vec<T>,
) -> Self {
self.conf.set_storage_devices(storage_devices);
self
}
pub fn build(self) -> VZVirtualMachineConfiguration {
self.conf
}
}
pub struct VZVirtualMachineConfiguration(StrongPtr);
impl VZVirtualMachineConfiguration {
fn new() -> VZVirtualMachineConfiguration {
unsafe {
let obj = StrongPtr::new(msg_send![class!(VZVirtualMachineConfiguration), new]);
VZVirtualMachineConfiguration(obj)
}
}
fn set_boot_loader<T: VZBootLoader>(&mut self, boot_loader: T) {
unsafe {
let _: () = msg_send![*self.0, setBootLoader: boot_loader.id()];
}
}
fn set_cpu_count(&mut self, cnt: usize) {
unsafe {
let _: () = msg_send![*self.0, setCPUCount: cnt];
}
}
fn set_memory_size(&mut self, size: usize) {
unsafe {
let _: () = msg_send![*self.0, setMemorySize: size];
}
}
fn set_entropy_devices<T: VZEntropyDeviceConfiguration>(&mut self, devices: Vec<T>) {
let device_ids = devices.iter().map(|x| x.id()).collect();
let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
unsafe {
let _: () = msg_send![*self.0, setEntropyDevices:*arr.p];
}
}
fn set_memory_balloon_devices<T: VZMemoryBalloonDeviceConfiguration>(
&mut self,
devices: Vec<T>,
) {
let device_ids = devices.iter().map(|x| x.id()).collect();
let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
unsafe {
let _: () = msg_send![*self.0, setMemoryBalloonDevices:*arr.p];
}
}
fn set_network_devices<T: VZNetworkDeviceConfiguration>(&mut self, devices: Vec<T>) {
let device_ids = devices.iter().map(|x| x.id()).collect();
let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
unsafe {
let _: () = msg_send![*self.0, setNetworkDevices:*arr.p];
}
}
fn set_serial_ports<T: VZSerialPortConfiguration>(&mut self, devices: Vec<T>) {
let device_ids = devices.iter().map(|x| x.id()).collect();
let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
unsafe {
let _: () = msg_send![*self.0, setSerialPorts:*arr.p];
}
}
fn set_socket_devices<T: VZSocketDeviceConfiguration>(&mut self, devices: Vec<T>) {
let device_ids = devices.iter().map(|x| x.id()).collect();
let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
unsafe {
let _: () = msg_send![*self.0, setSocketDevices:*arr.p];
}
}
fn set_storage_devices<T: VZStorageDeviceConfiguration>(&mut self, devices: Vec<T>) {
let device_ids = devices.iter().map(|x| x.id()).collect();
let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
unsafe {
let _: () = msg_send![*self.0, setStorageDevices:*arr.p];
}
}
pub fn validate_with_error(&self) -> Result<BOOL, NSError> {
unsafe {
let error = NSError(StrongPtr::new(0 as Id));
let obj: Id = msg_send![*self.0, validateWithError: &(*error.0)];
if error.code() != 0 {
Err(error)
} else {
Ok(obj as BOOL)
}
}
}
}
#[derive(Clone)]
pub struct VZVirtualMachine(StrongPtr);
#[derive(Debug)]
pub enum VZVirtualMachineState {
VZVirtualMachineStateStopped,
VZVirtualMachineStateRunning,
VZVirtualMachineStatePaused,
VZVirtualMachineStateError,
VZVirtualMachineStateStarting,
VZVirtualMachineStatePausing,
VZVirtualMachineStateResuming,
Other,
}
impl VZVirtualMachine {
pub fn new(conf: VZVirtualMachineConfiguration, queue: Id) -> VZVirtualMachine {
unsafe {
let i: Id = msg_send![class!(VZVirtualMachine), alloc];
let p = StrongPtr::new(msg_send![i, initWithConfiguration:*conf.0 queue:queue]);
VZVirtualMachine(p)
}
}
pub fn start_with_completion_handler(&self, completion_handler: &Block<(Id,), ()>) {
unsafe {
let _: Id = msg_send![*self.0, startWithCompletionHandler: completion_handler];
}
}
pub unsafe fn request_stop_with_error(&mut self) -> Result<bool, NSError> {
let error = NSError(StrongPtr::new(0 as Id));
let ret: BOOL = msg_send![*self.0, requestStopWithError:*error.0];
if error.code() != 0 {
Err(error)
} else {
Ok(ret == 1i8)
}
}
pub fn supported() -> bool {
unsafe {
let b: BOOL = msg_send![class!(VZVirtualMachine), isSupported];
b == YES
}
}
pub unsafe fn state(&self) -> VZVirtualMachineState {
let n: isize = msg_send![*self.0, state];
match n {
0 => VZVirtualMachineState::VZVirtualMachineStateStopped,
1 => VZVirtualMachineState::VZVirtualMachineStateRunning,
2 => VZVirtualMachineState::VZVirtualMachineStatePaused,
3 => VZVirtualMachineState::VZVirtualMachineStateError,
4 => VZVirtualMachineState::VZVirtualMachineStateStarting,
5 => VZVirtualMachineState::VZVirtualMachineStatePausing,
6 => VZVirtualMachineState::VZVirtualMachineStateResuming,
_ => VZVirtualMachineState::Other,
}
}
}