use winapi::shared::ntdef::HRESULT;
use winapi::shared::winerror::SUCCEEDED;
use crate::os::win::ComPtr;
pub fn call<TFunction, TStatusCode, T>(function: TFunction) -> Result<T, std::io::Error>
where
TFunction: FnOnce(*mut T) -> TStatusCode,
TStatusCode: HrLikeStatusCode,
{
raw_call(function).map_err(TStatusCode::error)
}
pub fn raw_call<TFunction, TStatusCode, T>(function: TFunction) -> Result<T, TStatusCode>
where
TFunction: FnOnce(*mut T) -> TStatusCode,
TStatusCode: HrLikeStatusCode,
{
let mut value = unsafe { std::mem::zeroed::<T>() };
let returned = function(&mut value);
match HrLikeStatusCode::ok(returned) {
true => Ok(value),
false => Err(returned),
}
}
pub fn com_call<TFunction, TStatusCode, T>(function: TFunction) -> Result<ComPtr<T>, std::io::Error>
where
TFunction: FnOnce(*mut *mut T) -> TStatusCode,
TStatusCode: HrLikeStatusCode,
{
com_raw_call(function).map_err(TStatusCode::error)
}
pub fn com_raw_call<TFunction, TStatusCode, T>(
function: TFunction,
) -> Result<ComPtr<T>, TStatusCode>
where
TFunction: FnOnce(*mut *mut T) -> TStatusCode,
TStatusCode: HrLikeStatusCode,
{
let mut value = std::ptr::null_mut();
let returned = function(&mut value);
match HrLikeStatusCode::ok(returned) {
true => Ok(unsafe { ComPtr::new(value) }),
false => Err(returned),
}
}
pub trait HrLikeStatusCode: Copy {
fn ok(self: Self) -> bool;
fn error(self: Self) -> std::io::Error;
}
impl HrLikeStatusCode for HRESULT {
fn ok(self: HRESULT) -> bool {
SUCCEEDED(self)
}
fn error(self: HRESULT) -> std::io::Error {
std::io::Error::from_raw_os_error(self)
}
}
impl HrLikeStatusCode for bool {
fn ok(self: bool) -> bool {
self
}
fn error(self: bool) -> std::io::Error {
std::io::Error::last_os_error()
}
}
impl HrLikeStatusCode for () {
fn ok(self: ()) -> bool {
true
}
fn error(self: ()) -> std::io::Error {
unreachable!();
}
}