Skip to content

Commit

Permalink
Allow returning Result from handler implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
Boddlnagg committed Sep 2, 2016
1 parent 9ee2ddb commit 309f94f
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 30 deletions.
17 changes: 8 additions & 9 deletions examples/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ extern crate runtimeobject;
use std::ptr;

use wrt::*;
use runtimeobject::*;

// TODO: re-export necessary types from winapi
use ::w::{
S_OK,
};

use wrt::windows::foundation::*;
use wrt::windows::devices::enumeration::*;
use wrt::windows::devices::midi::*;
Expand Down Expand Up @@ -50,6 +43,9 @@ fn run() {
let mut deviceInformationStatics = IDeviceInformationStatics::factory();

unsafe {
use runtimeobject::*;
use ::w::S_OK;

// Test some error reporting by using an invalid device selector
let wrongDeviceSelector: FastHString = "Foobar".into();
let res = deviceInformationStatics.find_all_async_aqs_filter(&wrongDeviceSelector);
Expand Down Expand Up @@ -103,7 +99,7 @@ fn run() {
let mut started = lock.lock().unwrap();
*started = true;
cvar.notify_one();
S_OK // TODO: return Result instead
Ok(())
});
unsafe { asyncOp.set_completed(&mut myHandler).unwrap() };
// local reference to myHandler is dropped here -> Release() is called
Expand Down Expand Up @@ -151,7 +147,10 @@ fn run() {
println!("Found remembered value: {} (index: {})", found, index);
}

assert!(unsafe { deviceInformationCollection.get_at(count + 42).is_err() }); // will be E_BOUNDS (out of bounds)
match unsafe { deviceInformationCollection.get_at(count + 42) } {
Err(e) => println!("Error getting element at {}: {:?}", count + 42, e), // will be out of bounds
Ok(_) => panic!("expected Error")
};

let array = &mut [true, false, false, true];
let boxed_array = unsafe { IPropertyValueStatics::factory().create_boolean_array(array) };
Expand Down
10 changes: 9 additions & 1 deletion src/result.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub type HRESULT = ::w::HRESULT; // re-export HRESULT from WinAPI

#[derive(Debug)]
// TODO: add more codes from https://msdn.microsoft.com/en-us/library/windows/desktop/dd542643(v=vs.85).aspx, especially the `RO_`-prefixed

#[derive(Debug, PartialEq, Eq)]
pub enum Error {
OperationAborted,
AccessDenied, // UnauthorizedAccessException in .NET (https://msdn.microsoft.com/en-us/library/awy7adbx(v=vs.110).aspx)
Expand All @@ -12,6 +14,8 @@ pub enum Error {
OutOfMemory, // OutOfMemoryException in .NET (https://msdn.microsoft.com/en-us/library/9ztbc5s1(v=vs.110).aspx)
InvalidPointer,
UnexpectedFailure,
OutOfBounds,
IllegalMethodCall,
Other(HRESULT)
}

Expand All @@ -30,6 +34,8 @@ impl Error {
::w::E_OUTOFMEMORY => OutOfMemory,
::w::E_POINTER => InvalidPointer,
::w::E_UNEXPECTED => UnexpectedFailure,
::w::E_BOUNDS => OutOfBounds,
::w::E_ILLEGAL_METHOD_CALL => IllegalMethodCall,
_ => Other(hr)
}
}
Expand All @@ -48,6 +54,8 @@ impl Error {
OutOfMemory => ::w::E_OUTOFMEMORY,
InvalidPointer => ::w::E_POINTER,
UnexpectedFailure => ::w::E_UNEXPECTED,
OutOfBounds => ::w::E_BOUNDS,
IllegalMethodCall => ::w::E_ILLEGAL_METHOD_CALL,
Other(hr) => hr,
}
}
Expand Down
46 changes: 26 additions & 20 deletions src/rt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,25 +366,25 @@ macro_rules! RT_INTERFACE {
macro_rules! RT_DELEGATE {
// without generic parameters
(delegate $interface:ident ($vtbl:ident, $imp:ident) [$iid:ident] {
$(#[cfg($cond_attr:meta)])* fn Invoke(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty
$(#[cfg($cond_attr:meta)])* fn Invoke(&mut self $(,$p:ident : $t:ty)*) -> HRESULT
}) => {
RT_INTERFACE!{basic $interface($vtbl) : IUnknown(::w::IUnknownVtbl) [$iid] {
$(#[cfg($cond_attr)])* fn Invoke(&mut self $(,$p : $t)*) -> $rtr
$(#[cfg($cond_attr)])* fn Invoke(&mut self $(,$p : $t)*) -> HRESULT
}}

impl $interface {
#[inline] pub fn new<_F_>(f: _F_) -> ComPtr<$interface>
where _F_: 'static + Send + FnMut($($t),*) -> $rtr, $interface: ComIid {
where _F_: 'static + Send + FnMut($($t),*) -> Result<()>, $interface: ComIid {
$imp::new(f).into_interface()
}
}

struct $imp<_F_> where _F_: 'static + Send + FnMut($($t),*) -> $rtr {
struct $imp<_F_> where _F_: 'static + Send + FnMut($($t),*) -> Result<()> {
invoke: _F_
}

impl<_F_> $imp<_F_>
where $interface: ComIid, _F_: 'static + Send + FnMut($($t),*) -> $rtr
where $interface: ComIid, _F_: 'static + Send + FnMut($($t),*) -> Result<()>
{
pub fn new(f: _F_) -> $imp<_F_> {
$imp {
Expand All @@ -394,7 +394,7 @@ macro_rules! RT_DELEGATE {
}

impl<_F_> ::rt::handler::ComClass<$interface> for $imp<_F_>
where $interface: ComIid, _F_: 'static + Send + FnMut($($t),*) -> $rtr
where $interface: ComIid, _F_: 'static + Send + FnMut($($t),*) -> Result<()>
{
fn get_vtbl() -> $vtbl {
$vtbl {
Expand All @@ -404,11 +404,14 @@ macro_rules! RT_DELEGATE {
Release: ::rt::handler::ComRepr_Release::<$imp<_F_>>,
},
Invoke: {
unsafe extern "system" fn Invoke<_F_>(this_: *mut $interface $(,$p : $t)*) -> $rtr
where $interface: ComIid, _F_: 'static + Send + FnMut($($t),*) -> $rtr
unsafe extern "system" fn Invoke<_F_>(this_: *mut $interface $(,$p : $t)*) -> HRESULT
where $interface: ComIid, _F_: 'static + Send + FnMut($($t),*) -> Result<()>
{
let this: &mut $imp<_F_> = ::rt::handler::ComClass::from_interface(this_);
(this.invoke)($($p),*)
match (this.invoke)($($p),*) {
Ok(()) => S_OK,
Err(err) => err.as_hresult()
}
}
Invoke::<_F_>
}
Expand All @@ -417,7 +420,7 @@ macro_rules! RT_DELEGATE {
}

/*impl<_F_> Drop for $imp<_F_>
where _F_: 'static + Send + FnMut($($t),*) -> $rtr
where _F_: 'static + Send + FnMut($($t),*) -> HRESULT
{
fn drop(&mut self) {
println!("DROPPED {}<...>!", stringify!($imp));
Expand All @@ -427,26 +430,26 @@ macro_rules! RT_DELEGATE {

// with generic parameters
(delegate $interface:ident<$($ht:ident),+> ($vtbl:ident, $imp:ident) [$iid:ident] {
$(#[cfg($cond_attr:meta)])* fn Invoke(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty
$(#[cfg($cond_attr:meta)])* fn Invoke(&mut self $(,$p:ident : $t:ty)*) -> HRESULT
}) => {
RT_INTERFACE!{basic $interface<$($ht),+>($vtbl) : IUnknown(::w::IUnknownVtbl) [$iid] {
$(#[cfg($cond_attr)])* fn Invoke(&mut self $(,$p : $t)*) -> $rtr
$(#[cfg($cond_attr)])* fn Invoke(&mut self $(,$p : $t)*) -> HRESULT
}}

impl<$($ht: RtType + 'static),+> $interface<$($ht),+> {
#[inline] pub fn new<_F_>(f: _F_) -> ComPtr<$interface<$($ht),+>>
where _F_: 'static + Send + FnMut($($t),*) -> $rtr, $interface<$($ht),+>: ComIid {
where _F_: 'static + Send + FnMut($($t),*) -> Result<()>, $interface<$($ht),+>: ComIid {
$imp::new(f).into_interface()
}
}

struct $imp<$($ht: RtType),+ , _F_> where _F_: 'static + Send + FnMut($($t),*) -> $rtr {
struct $imp<$($ht: RtType),+ , _F_> where _F_: 'static + Send + FnMut($($t),*) -> Result<()> {
invoke: _F_,
phantom: ::std::marker::PhantomData<($($ht),+)>
}

impl<$($ht: RtType + 'static),+ , _F_> $imp<$($ht),+ , _F_>
where $interface<$($ht),+>: ComIid, _F_: 'static + Send + FnMut($($t),*) -> $rtr
where $interface<$($ht),+>: ComIid, _F_: 'static + Send + FnMut($($t),*) -> Result<()>
{
pub fn new(f: _F_) -> $imp<$($ht),+ , _F_> {
$imp {
Expand All @@ -457,7 +460,7 @@ macro_rules! RT_DELEGATE {
}

impl<$($ht: RtType + 'static),+ , _F_> ::rt::handler::ComClass<$interface<$($ht),+>> for $imp<$($ht),+ , _F_>
where $interface<$($ht),+>: ComIid, _F_: 'static + Send + FnMut($($t),*) -> $rtr
where $interface<$($ht),+>: ComIid, _F_: 'static + Send + FnMut($($t),*) -> Result<()>
{
fn get_vtbl() -> $vtbl<$($ht),+> {
$vtbl::<$($ht),+> {
Expand All @@ -467,11 +470,14 @@ macro_rules! RT_DELEGATE {
Release: ::rt::handler::ComRepr_Release::<$imp<$($ht),+ , _F_>>,
},
Invoke: {
unsafe extern "system" fn Invoke<$($ht: RtType + 'static),+ , _F_>(this_: *mut $interface<$($ht),+> $(,$p : $t)*) -> $rtr
where $interface<$($ht),+>: ComIid, _F_: 'static + Send + FnMut($($t),*) -> $rtr
unsafe extern "system" fn Invoke<$($ht: RtType + 'static),+ , _F_>(this_: *mut $interface<$($ht),+> $(,$p : $t)*) -> HRESULT
where $interface<$($ht),+>: ComIid, _F_: 'static + Send + FnMut($($t),*) -> Result<()>
{
let this: &mut $imp<$($ht),+ , _F_> = ::rt::handler::ComClass::from_interface(this_);
(this.invoke)($($p),*)
match (this.invoke)($($p),*) {
Ok(()) => S_OK,
Err(err) => err.as_hresult()
}
}
Invoke::<$($ht),+ , _F_>
}
Expand All @@ -480,7 +486,7 @@ macro_rules! RT_DELEGATE {
}

/*impl<$($ht: RtType),+ , _F_> Drop for $imp<$($ht),+ , _F_>
where _F_: 'static + Send + FnMut($($t),*) -> $rtr
where _F_: 'static + Send + FnMut($($t),*) -> HRESULT
{
fn drop(&mut self) {
println!("DROPPED {}<...>!", stringify!($imp));
Expand Down

0 comments on commit 309f94f

Please sign in to comment.