Skip to content

Commit

Permalink
Improve HRESULT ergonomics (#2843)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Feb 13, 2024
1 parent ed2ef0d commit 7ce7894
Show file tree
Hide file tree
Showing 529 changed files with 52,162 additions and 52,147 deletions.
26 changes: 21 additions & 5 deletions crates/libs/bindgen/src/rust/com_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, kind: metadata::Interface
#features
pub unsafe fn #name<#generics>(&self, #params) -> ::windows_core::Result<T> #where_clause {
let mut result__ = ::std::ptr::null_mut();
(::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args).from_abi(result__)
(::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args).and_then(||::windows_core::Type::from_abi(result__))
}
}
}
Expand All @@ -54,13 +54,20 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, kind: metadata::Interface
let args = writer.win32_args(&signature.params, kind);
let params = writer.win32_params(&signature.params, kind);
let return_type = signature.params[signature.params.len() - 1].ty.deref();

let map = if metadata::type_is_blittable(&return_type) {
quote! { map(||result__) }
} else {
quote! { and_then(||::windows_core::Type::from_abi(result__)) }
};

let return_type = writer.type_name(&return_type);

quote! {
#features
pub unsafe fn #name<#generics>(&self, #params) -> ::windows_core::Result<#return_type> #where_clause {
let mut result__ = ::std::mem::zeroed();
(::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args).from_abi(result__)
(::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args).#map
}
}
}
Expand All @@ -80,24 +87,33 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, kind: metadata::Interface
let params = writer.win32_params(&signature.params, kind);
let return_type = signature.params[signature.params.len() - 1].ty.deref();
let is_nullable = metadata::type_is_nullable(&return_type);
let return_type = writer.type_name(&return_type);

if is_nullable {
let return_type = writer.type_name(&return_type);

quote! {
#features
pub unsafe fn #name<#generics>(&self, #params) -> ::windows_core::Result<#return_type> #where_clause {
let mut result__ = ::std::mem::zeroed();
(::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args);
::windows_core::from_abi(result__)
::windows_core::Type::from_abi(result__)
}
}
} else {
let map = if metadata::type_is_blittable(&return_type) {
quote! { result__ }
} else {
quote! { ::std::mem::transmute(result__) }
};

let return_type = writer.type_name(&return_type);

quote! {
#features
pub unsafe fn #name<#generics>(&self, #params) -> #return_type #where_clause {
let mut result__ = ::std::mem::zeroed();
(::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args);
::std::mem::transmute(result__)
#map
}
}
}
Expand Down
26 changes: 21 additions & 5 deletions crates/libs/bindgen/src/rust/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn gen_win_function(writer: &Writer, namespace: &str, def: metadata::MethodDef)
pub unsafe fn #name<#generics>(#params) -> ::windows_core::Result<T> #where_clause {
#link
let mut result__ = ::std::ptr::null_mut();
#name(#args).from_abi(result__)
#name(#args).and_then(||::windows_core::Type::from_abi(result__))
}
}
}
Expand All @@ -76,6 +76,13 @@ fn gen_win_function(writer: &Writer, namespace: &str, def: metadata::MethodDef)
let args = writer.win32_args(&signature.params, kind);
let params = writer.win32_params(&signature.params, kind);
let return_type = signature.params[signature.params.len() - 1].ty.deref();

let map = if metadata::type_is_blittable(&return_type) {
quote! { map(||result__) }
} else {
quote! { and_then(||::windows_core::Type::from_abi(result__)) }
};

let return_type = writer.type_name(&return_type);

quote! {
Expand All @@ -84,7 +91,7 @@ fn gen_win_function(writer: &Writer, namespace: &str, def: metadata::MethodDef)
pub unsafe fn #name<#generics>(#params) -> ::windows_core::Result<#return_type> #where_clause {
#link
let mut result__ = ::std::mem::zeroed();
#name(#args).from_abi(result__)
#name(#args).#map
}
}
}
Expand All @@ -106,28 +113,37 @@ fn gen_win_function(writer: &Writer, namespace: &str, def: metadata::MethodDef)
let params = writer.win32_params(&signature.params, kind);
let return_type = signature.params[signature.params.len() - 1].ty.deref();
let is_nullable = metadata::type_is_nullable(&return_type);
let return_type = writer.type_name(&return_type);

if is_nullable {
let return_type = writer.type_name(&return_type);

quote! {
#features
#[inline]
pub unsafe fn #name<#generics>(#params) -> ::windows_core::Result<#return_type> #where_clause {
#link
let mut result__ = ::std::mem::zeroed();
#name(#args);
::windows_core::from_abi(result__.assume_init())
::windows_core::Type::from_abi(result__.assume_init())
}
}
} else {
let map = if metadata::type_is_blittable(&return_type) {
quote! { result__ }
} else {
quote! { ::std::mem::transmute(result__) }
};

let return_type = writer.type_name(&return_type);

quote! {
#features
#[inline]
pub unsafe fn #name<#generics>(#params) -> #return_type #where_clause {
#link
let mut result__ = ::std::mem::zeroed();
#name(#args);
::std::mem::transmute(result__)
#map
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions crates/libs/bindgen/src/rust/winrt_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,20 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, generic_types: &[metadata
quote! {
let mut result__ = ::core::mem::MaybeUninit::zeroed();
(::windows_core::Interface::vtable(this).#vname)(::windows_core::Interface::as_raw(this), #args #return_arg)
.and_then(|| result__.assume_init())
.map(|| result__.assume_init())
}
}
_ => {
let map = if metadata::type_is_blittable(&signature.return_type) {
quote! { map(||result__) }
} else {
quote! { and_then(|| ::windows_core::Type::from_abi(result__)) }
};

quote! {
let mut result__ = ::std::mem::zeroed();
(::windows_core::Interface::vtable(this).#vname)(::windows_core::Interface::as_raw(this), #args #return_arg)
.from_abi(result__)
.#map
}
}
};
Expand Down
38 changes: 10 additions & 28 deletions crates/libs/core/src/hresult.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,44 +40,26 @@ impl HRESULT {
}
}

/// Returns the [`Option`] as a [`Result`] if the option is a [`Some`] value, returning
/// a suitable error if not.
pub fn and_some<T: Interface>(self, some: Option<T>) -> Result<T> {
if self.is_ok() {
if let Some(result) = some {
Ok(result)
} else {
Err(Error::OK)
}
} else {
Err(Error::from(self))
}
}

/// Calls `op` if `self` is a success code, otherwise returns [`HRESULT`]
/// converted to [`Result<T>`].
#[inline]
pub fn and_then<F, T>(self, op: F) -> Result<T>
pub fn map<F, T>(self, op: F) -> Result<T>
where
F: FnOnce() -> T,
{
self.ok()?;
Ok(op())
}

/// If the [`Result`] is [`Ok`] converts the `T::Abi` into `T`.
///
/// # Safety
///
/// Safe to call if
/// * `abi` is initialized if `self` is `Ok`
/// * `abi` can be safely transmuted to `T`
pub unsafe fn from_abi<T: Type<T>>(self, abi: T::Abi) -> Result<T> {
if self.is_ok() {
T::from_abi(abi)
} else {
Err(Error::from(self))
}
/// Calls `op` if `self` is a success code, otherwise returns [`HRESULT`]
/// converted to [`Result<T>`].
#[inline]
pub fn and_then<F, T>(self, op: F) -> Result<T>
where
F: FnOnce() -> Result<T>,
{
self.ok()?;
op()
}

/// The error message describing the error.
Expand Down
Loading

0 comments on commit 7ce7894

Please sign in to comment.