From 309f94f0285a72513e4344790629d3fbf793d928 Mon Sep 17 00:00:00 2001 From: Patrick Reisert Date: Fri, 2 Sep 2016 18:18:21 +0200 Subject: [PATCH] Allow returning Result from handler implementations --- examples/test.rs | 17 ++++++++--------- src/result.rs | 10 +++++++++- src/rt/mod.rs | 46 ++++++++++++++++++++++++++-------------------- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/examples/test.rs b/examples/test.rs index 6ee20a5..ccdbe8c 100644 --- a/examples/test.rs +++ b/examples/test.rs @@ -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::*; @@ -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); @@ -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 @@ -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) }; diff --git a/src/result.rs b/src/result.rs index 7974fa0..9a7c831 100644 --- a/src/result.rs +++ b/src/result.rs @@ -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) @@ -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) } @@ -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) } } @@ -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, } } diff --git a/src/rt/mod.rs b/src/rt/mod.rs index 7b29249..82a2d90 100644 --- a/src/rt/mod.rs +++ b/src/rt/mod.rs @@ -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 { @@ -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 { @@ -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_> } @@ -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)); @@ -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 { @@ -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),+> { @@ -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_> } @@ -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));