#[cfg(not(feature = "macos-12-1"))]
use std::alloc::LayoutError;
use applevisor_sys::*;
pub type Result<T> = std::result::Result<T, HypervisorError>;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum HypervisorError {
BadArgument,
Busy,
Denied,
Error,
Fault,
IllegalState,
NoDevice,
NoResources,
Unknown(hv_return_t),
Unsupported,
#[cfg(not(feature = "macos-12-1"))]
LayoutError,
}
impl HypervisorError {
pub(crate) fn as_str(&self) -> &'static str {
match self {
Self::BadArgument => "function call has an invalid argument",
Self::Busy => "owning resource is busy",
Self::Denied => "operation not allowed by the system",
Self::Error => "operation unsuccessful",
Self::Fault => "hypervisor fault",
Self::IllegalState => "guest in an illegal state",
Self::NoDevice => "no VM or vCPU available",
Self::NoResources => "no host resources available to complete the request",
Self::Unknown(_) => "unknown error",
Self::Unsupported => "unsupported operation",
#[cfg(not(feature = "macos-12-1"))]
Self::LayoutError => "layout error",
}
}
}
impl From<hv_return_t> for HypervisorError {
fn from(code: hv_return_t) -> Self {
match code {
x if x == hv_error_t::HV_BAD_ARGUMENT as hv_return_t => Self::BadArgument,
x if x == hv_error_t::HV_BUSY as hv_return_t => Self::Busy,
x if x == hv_error_t::HV_DENIED as hv_return_t => Self::Denied,
x if x == hv_error_t::HV_ERROR as hv_return_t => Self::Error,
x if x == hv_error_t::HV_FAULT as hv_return_t => Self::Fault,
x if x == hv_error_t::HV_ILLEGAL_GUEST_STATE as hv_return_t => Self::IllegalState,
x if x == hv_error_t::HV_NO_DEVICE as hv_return_t => Self::NoDevice,
x if x == hv_error_t::HV_NO_RESOURCES as hv_return_t => Self::NoResources,
x if x == hv_error_t::HV_UNSUPPORTED as hv_return_t => Self::Unsupported,
_ => Self::Unknown(code),
}
}
}
#[cfg(not(feature = "macos-12-1"))]
impl From<LayoutError> for HypervisorError {
fn from(_err: LayoutError) -> Self {
HypervisorError::LayoutError
}
}
impl From<HypervisorError> for hv_return_t {
fn from(err: HypervisorError) -> Self {
match err {
HypervisorError::BadArgument => hv_error_t::HV_BAD_ARGUMENT as hv_return_t,
HypervisorError::Busy => hv_error_t::HV_BUSY as hv_return_t,
HypervisorError::Denied => hv_error_t::HV_DENIED as hv_return_t,
HypervisorError::Error => hv_error_t::HV_ERROR as hv_return_t,
HypervisorError::Fault => hv_error_t::HV_FAULT as hv_return_t,
HypervisorError::IllegalState => hv_error_t::HV_ILLEGAL_GUEST_STATE as hv_return_t,
HypervisorError::NoDevice => hv_error_t::HV_NO_DEVICE as hv_return_t,
HypervisorError::NoResources => hv_error_t::HV_NO_RESOURCES as hv_return_t,
HypervisorError::Unsupported => hv_error_t::HV_UNSUPPORTED as hv_return_t,
HypervisorError::Unknown(code) => code,
#[cfg(not(feature = "macos-12-1"))]
HypervisorError::LayoutError => hv_error_t::HV_ERROR as hv_return_t,
}
}
}
impl std::error::Error for HypervisorError {}
impl std::fmt::Display for HypervisorError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} (error {:#08x})",
self.as_str(),
Into::<hv_return_t>::into(*self)
)
}
}
impl std::fmt::Debug for HypervisorError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("HypervisorError")
.field("code", &Into::<hv_return_t>::into(*self))
.field("description", &self.as_str())
.finish()
}
}