Skip to content

Commit

Permalink
ref
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr committed May 9, 2024
1 parent fed948b commit 604502c
Show file tree
Hide file tree
Showing 26 changed files with 542 additions and 145 deletions.
2 changes: 1 addition & 1 deletion crates/libs/bindgen/src/rust/handles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub fn gen_win_handle(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
dependency.push_str(type_name.name());

tokens.combine(&quote! {
impl windows_core::CanInto<#dependency> for #ident {}
impl windows_core::imp::CanInto<#dependency> for #ident {}
impl From<#ident> for #dependency {
fn from(value: #ident) -> Self {
Self(value.0)
Expand Down
4 changes: 2 additions & 2 deletions crates/libs/bindgen/src/rust/interfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
let cfg = writer.cfg_features(&cfg.union(cfg::type_cfg(writer, ty)));
tokens.combine(&quote! {
#cfg
impl<#constraints> windows_core::CanInto<#into> for #ident {}
impl<#constraints> windows_core::imp::CanInto<#into> for #ident {}
});
}
}
Expand All @@ -152,7 +152,7 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
let cfg = writer.cfg_features(&cfg.union(cfg::type_cfg(writer, &interface.ty)));
tokens.combine(&quote! {
#cfg
impl<#constraints> windows_core::CanInto<#into> for #ident { const QUERY: bool = true; }
impl<#constraints> windows_core::imp::CanInto<#into> for #ident { const QUERY: bool = true; }
});
}
}
Expand Down
5 changes: 5 additions & 0 deletions crates/libs/core/src/imp/can_into.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub trait CanInto<T>: Sized {
const QUERY: bool = false;
}

impl<T> CanInto<T> for T where T: Clone {}
6 changes: 3 additions & 3 deletions crates/libs/core/src/imp/com_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,9 +428,9 @@ impl<T: windows_core::RuntimeType + 'static> std::ops::Deref for IReference<T> {
unsafe { std::mem::transmute(self) }
}
}
impl<T: windows_core::RuntimeType + 'static> windows_core::CanInto<windows_core::IUnknown> for IReference<T> {}
impl<T: windows_core::RuntimeType + 'static> windows_core::CanInto<windows_core::IInspectable> for IReference<T> {}
impl<T: windows_core::RuntimeType + 'static> windows_core::CanInto<IPropertyValue> for IReference<T> {
impl<T: windows_core::RuntimeType + 'static> windows_core::imp::CanInto<windows_core::IUnknown> for IReference<T> {}
impl<T: windows_core::RuntimeType + 'static> windows_core::imp::CanInto<windows_core::IInspectable> for IReference<T> {}
impl<T: windows_core::RuntimeType + 'static> windows_core::imp::CanInto<IPropertyValue> for IReference<T> {
const QUERY: bool = true;
}
impl<T: windows_core::RuntimeType + 'static> IReference<T> {
Expand Down
6 changes: 4 additions & 2 deletions crates/libs/core/src/imp/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod bindings;
mod can_into;
mod com_bindings;
mod delay_load;
mod factory_cache;
Expand All @@ -10,6 +11,7 @@ mod waiter;
mod weak_ref_count;

pub use bindings::*;
pub use can_into::*;
pub use com_bindings::*;
pub use delay_load::*;
pub use factory_cache::*;
Expand All @@ -34,7 +36,7 @@ pub fn wide_trim_end(mut wide: &[u16]) -> &[u16] {
#[macro_export]
macro_rules! interface_hierarchy {
($child:ident, $parent:ty) => {
impl ::windows_core::CanInto<$parent> for $child {}
impl ::windows_core::imp::CanInto<$parent> for $child {}
impl ::core::convert::From<&$child> for &$parent {
fn from(value: &$child) -> Self {
unsafe { ::core::mem::transmute(value) }
Expand All @@ -59,7 +61,7 @@ pub use interface_hierarchy;
#[macro_export]
macro_rules! required_hierarchy {
($child:ident, $parent:ty) => {
impl ::windows_core::CanInto<$parent> for $child { const QUERY: bool = true; }
impl ::windows_core::imp::CanInto<$parent> for $child { const QUERY: bool = true; }
};
($child:ident, $first:ty, $($rest:ty),+) => {
$crate::imp::required_hierarchy!($child, $first);
Expand Down
8 changes: 8 additions & 0 deletions crates/libs/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ mod handles;
mod inspectable;
mod interface;
mod param;
mod param_mut;
mod param_value;
mod r#ref;
mod ref_mut;
mod runtime_name;
mod runtime_type;
mod scoped_interface;
Expand All @@ -38,7 +42,11 @@ pub use handles::*;
pub use inspectable::*;
pub use interface::*;
pub use param::*;
pub use param_mut::*;
pub use param_value::*;
pub use r#ref::*;
pub use r#type::*;
pub use ref_mut::*;
pub use runtime_name::*;
pub use runtime_type::*;
pub use scoped_interface::*;
Expand Down
28 changes: 2 additions & 26 deletions crates/libs/core/src/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ where
T: TypeKind<TypeKind = InterfaceType> + Clone,
T: Interface,
U: Interface,
U: CanInto<T>,
U: imp::CanInto<T>,
{
unsafe fn param(self) -> ParamValue<T> {
if U::QUERY {
Expand All @@ -52,7 +52,7 @@ impl<T, U> Param<T, CopyType> for U
where
T: TypeKind<TypeKind = CopyType> + Clone,
U: TypeKind<TypeKind = CopyType> + Clone,
U: CanInto<T>,
U: imp::CanInto<T>,
{
unsafe fn param(self) -> ParamValue<T> {
ParamValue::Owned(std::mem::transmute_copy(&self))
Expand Down Expand Up @@ -82,27 +82,3 @@ impl Param<PCSTR> for PSTR {
ParamValue::Owned(PCSTR(self.0))
}
}

#[doc(hidden)]
pub enum ParamValue<T: Type<T>> {
Owned(T),
Borrowed(T::Abi),
}

impl<T: Type<T>> ParamValue<T> {
pub fn abi(&self) -> T::Abi {
unsafe {
match self {
Self::Owned(item) => std::mem::transmute_copy(item),
Self::Borrowed(borrowed) => std::mem::transmute_copy(borrowed),
}
}
}
}

#[doc(hidden)]
pub trait CanInto<T>: Sized {
const QUERY: bool = false;
}

impl<T> CanInto<T> for T where T: Clone {}
56 changes: 56 additions & 0 deletions crates/libs/core/src/param_mut.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use super::*;

/// Provides automatic parameter conversion in cases where the Windows API expects implicit conversion support.
///
/// This is a mutable version of [Param] meant to support out parameters.
/// There is no need to implement this trait. Blanket implementations are provided for all applicable Windows types.
pub trait ParamMut<T: TypeKind, C = <T as TypeKind>::TypeKind>: Sized
where
T: Type<T>,
{
#[doc(hidden)]
unsafe fn borrow_mut(&self) -> RefMut<'_, T>;
}

impl<T> ParamMut<T, CloneType> for &mut T
where
T: TypeKind<TypeKind = CloneType> + Clone + Default,
{
unsafe fn borrow_mut(&self) -> RefMut<'_, T> {
let this: &mut T = std::mem::transmute_copy(self);
std::mem::take(this);
std::mem::transmute_copy(self)
}
}

impl<T> ParamMut<T, CopyType> for &mut T
where
T: TypeKind<TypeKind = CopyType> + Clone + Default,
{
unsafe fn borrow_mut(&self) -> RefMut<'_, T> {
std::mem::transmute_copy(self)
}
}

impl<T> ParamMut<T, InterfaceType> for &mut Option<T>
where
T: TypeKind<TypeKind = InterfaceType> + Clone,
{
unsafe fn borrow_mut(&self) -> RefMut<'_, T> {
let this: &mut Option<T> = std::mem::transmute_copy(self);
std::mem::take(this);
std::mem::transmute_copy(self)
}
}

impl<T> ParamMut<T> for Option<&mut T>
where
T: Type<T>,
{
unsafe fn borrow_mut(&self) -> RefMut<'_, T> {
match self {
Some(this) => std::mem::transmute_copy(this),
None => std::mem::zeroed(),
}
}
}
23 changes: 23 additions & 0 deletions crates/libs/core/src/param_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use super::*;

#[doc(hidden)]
pub enum ParamValue<T: Type<T>> {
Owned(T),
Borrowed(T::Abi),
}

impl<T: Type<T>> ParamValue<T> {
// TODO: replace with `borrow` in windows-bindgen
pub fn abi(&self) -> T::Abi {
unsafe {
match self {
Self::Owned(item) => std::mem::transmute_copy(item),
Self::Borrowed(borrowed) => std::mem::transmute_copy(borrowed),
}
}
}

pub fn borrow(&self) -> Ref<'_, T> {
unsafe { std::mem::transmute_copy(&self.abi()) }
}
}
17 changes: 17 additions & 0 deletions crates/libs/core/src/ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use super::*;

/// A borrowed type with the same memory layout as the type itself that can be used to construct ABI-compatible function signatures.
#[repr(transparent)]
pub struct Ref<'a, T: Type<T>>(T::Abi, std::marker::PhantomData<&'a T>);

impl<'a, T: Type<T>> Ref<'a, T> {
/// Reads the borrowed value.
pub fn read(&self) -> &T::Default {
unsafe { std::mem::transmute(&self.0) }
}

/// Clones the borrowed value.
pub fn ok(&self) -> Result<T> {
T::from_default(self.read())
}
}
25 changes: 25 additions & 0 deletions crates/libs/core/src/ref_mut.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use super::*;

/// A borrowed type with the same memory layout as the type itself that can be used to construct ABI-compatible function signatures.
///
/// This is a mutable version of [Ref] meant to support out parameters.
#[repr(transparent)]
pub struct RefMut<'a, T: Type<T>>(*mut T::Abi, std::marker::PhantomData<&'a T>);

impl<'a, T: Type<T>> RefMut<'a, T> {
/// Returns `true` if the argument is null.
pub fn is_null(&self) -> bool {
self.0.is_null()
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
pub fn write(self, value: T::Default) -> Result<()> {
if self.0.is_null() {
Err(Error::from_hresult(imp::E_POINTER))
} else {
unsafe { *self.0 = std::mem::transmute_copy(&value) }
std::mem::forget(value);
Ok(())
}
}
}
2 changes: 1 addition & 1 deletion crates/libs/interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ targets = []
proc-macro = true

[dependencies]
syn = { version = "2.0", default-features = false, features = ["parsing", "proc-macro", "printing", "full", "derive"] }
syn = { version = "2.0", default-features = false, features = ["parsing", "proc-macro", "printing", "full", "derive", "clone-impls"] }
quote = "1.0"
proc-macro2 = "1.0"
Loading

0 comments on commit 604502c

Please sign in to comment.