Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stock collection support for IIterable #2346

Merged
merged 9 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ jobs:
cargo clippy -p test_bstr &&
cargo clippy -p test_calling_convention &&
cargo clippy -p test_cfg_generic &&
cargo clippy -p test_collections &&
cargo clippy -p test_component &&
cargo clippy -p test_component_client &&
cargo clippy -p test_const_fields &&
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ jobs:
cargo test --target ${{ matrix.target }} -p test_bstr &&
cargo test --target ${{ matrix.target }} -p test_calling_convention &&
cargo test --target ${{ matrix.target }} -p test_cfg_generic &&
cargo test --target ${{ matrix.target }} -p test_collections &&
cargo test --target ${{ matrix.target }} -p test_component &&
cargo test --target ${{ matrix.target }} -p test_component_client &&
cargo test --target ${{ matrix.target }} -p test_const_fields &&
Expand All @@ -133,8 +134,8 @@ jobs:
cargo test --target ${{ matrix.target }} -p test_enums &&
cargo test --target ${{ matrix.target }} -p test_error &&
cargo test --target ${{ matrix.target }} -p test_event &&
cargo test --target ${{ matrix.target }} -p test_extensions &&
cargo clean &&
cargo test --target ${{ matrix.target }} -p test_extensions &&
cargo test --target ${{ matrix.target }} -p test_handles &&
cargo test --target ${{ matrix.target }} -p test_helpers &&
cargo test --target ${{ matrix.target }} -p test_implement &&
Expand Down
12 changes: 6 additions & 6 deletions crates/libs/bindgen/src/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream {
pub fn #interface_type<R, F: FnOnce(&#interface_type) -> ::windows::core::Result<R>>(
callback: F,
) -> ::windows::core::Result<R> {
static SHARED: ::windows::core::FactoryCache<#name, #interface_type> =
::windows::core::FactoryCache::new();
static SHARED: ::windows::imp::FactoryCache<#name, #interface_type> =
::windows::imp::FactoryCache::new();
SHARED.call(callback)
}
});
Expand All @@ -86,11 +86,11 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream {
pub fn new() -> ::windows::core::Result<Self> {
Self::IActivationFactory(|f| f.ActivateInstance::<Self>())
}
fn IActivationFactory<R, F: FnOnce(&::windows::core::IGenericFactory) -> ::windows::core::Result<R>>(
fn IActivationFactory<R, F: FnOnce(&::windows::imp::IGenericFactory) -> ::windows::core::Result<R>>(
callback: F,
) -> ::windows::core::Result<R> {
static SHARED: ::windows::core::FactoryCache<#name, ::windows::core::IGenericFactory> =
::windows::core::FactoryCache::new();
static SHARED: ::windows::imp::FactoryCache<#name, ::windows::imp::IGenericFactory> =
::windows::imp::FactoryCache::new();
SHARED.call(callback)
}
}
Expand Down Expand Up @@ -176,7 +176,7 @@ fn gen_conversions(
let features = gen.cfg_features(cfg);
let mut tokens = quote! {
#features
::windows::core::interface_hierarchy!(#name, ::windows::core::IUnknown, ::windows::core::IInspectable);
::windows::imp::interface_hierarchy!(#name, ::windows::core::IUnknown, ::windows::core::IInspectable);
};

for interface in interfaces {
Expand Down
10 changes: 5 additions & 5 deletions crates/libs/bindgen/src/delegates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream {
pub fn new<#fn_constraint>(invoke: F) -> Self {
let com = #boxed::<#generic_names F> {
vtable: &#boxed::<#generic_names F>::VTABLE,
count: ::windows::core::RefCount::new(1),
count: ::windows::imp::RefCount::new(1),
invoke,
};
unsafe {
::core::mem::transmute(::windows::core::alloc::boxed::Box::new(com))
::core::mem::transmute(::std::boxed::Box::new(com))
}
}
#invoke
Expand All @@ -103,7 +103,7 @@ fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream {
struct #boxed<#generic_names #fn_constraint> where #constraints {
vtable: *const #vtbl<#generic_names>,
invoke: F,
count: ::windows::core::RefCount,
count: ::windows::imp::RefCount,
}
#features
impl<#constraints #fn_constraint> #boxed<#generic_names F> {
Expand All @@ -117,7 +117,7 @@ fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream {

*interface = if iid == &<#ident as ::windows::core::Interface>::IID ||
iid == &<::windows::core::IUnknown as ::windows::core::Interface>::IID ||
iid == &<::windows::core::IAgileObject as ::windows::core::Interface>::IID {
iid == &<::windows::imp::IAgileObject as ::windows::core::Interface>::IID {
&mut (*this).vtable as *mut _ as _
} else {
::core::ptr::null_mut()
Expand All @@ -141,7 +141,7 @@ fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream {
let remaining = (*this).count.release();

if remaining == 0 {
let _ = ::windows::core::alloc::boxed::Box::from_raw(this);
let _ = ::std::boxed::Box::from_raw(this);
}

remaining
Expand Down
2 changes: 1 addition & 1 deletion crates/libs/bindgen/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream {
tokens.combine(&quote! {
#features
impl ::windows::core::RuntimeType for #ident {
const SIGNATURE: ::windows::core::ConstBuffer = ::windows::core::ConstBuffer::from_slice(#signature);
const SIGNATURE: ::windows::imp::ConstBuffer = ::windows::imp::ConstBuffer::from_slice(#signature);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#[::windows::core::implement(IIterable<T>)]
struct Iterable<T>
where
T: ::windows::core::RuntimeType + 'static,
<T as ::windows::core::Type<T>>::Default: ::std::clone::Clone,
{
values: std::vec::Vec<T::Default>,
}

impl<T> IIterable_Impl<T> for Iterable<T>
where
T: ::windows::core::RuntimeType,
<T as ::windows::core::Type<T>>::Default: ::std::clone::Clone,
{
fn First(&self) -> ::windows::core::Result<IIterator<T>> {
unsafe {
// TODO: ideally we can do an AddRef rather than a QI here (via cast)...
// and then we can get rid of the unsafe as well.
Ok(Iterator {
owner: self.cast()?,
current: 0.into(),
}
.into())
}
}
}

#[::windows::core::implement(IIterator<T>)]
struct Iterator<T>
where
T: ::windows::core::RuntimeType + 'static,
<T as ::windows::core::Type<T>>::Default: ::std::clone::Clone,
{
owner: IIterable<T>,
current: ::std::sync::atomic::AtomicUsize,
}

impl<T> IIterator_Impl<T> for Iterator<T>
where
T: ::windows::core::RuntimeType,
<T as ::windows::core::Type<T>>::Default: ::std::clone::Clone,
{
fn Current(&self) -> ::windows::core::Result<T> {
let owner = ::windows::core::AsImpl::as_impl(&self.owner);
let current = self.current.load(::std::sync::atomic::Ordering::Relaxed);

if owner.values.len() > current {
T::from_default(&owner.values[current])
} else {
Err(::windows::imp::E_BOUNDS.into())
}
}

fn HasCurrent(&self) -> ::windows::core::Result<bool> {
let owner = ::windows::core::AsImpl::as_impl(&self.owner);
let current = self.current.load(::std::sync::atomic::Ordering::Relaxed);

Ok(owner.values.len() > current)
}

fn MoveNext(&self) -> ::windows::core::Result<bool> {
let owner = ::windows::core::AsImpl::as_impl(&self.owner);
let current = self.current.load(::std::sync::atomic::Ordering::Relaxed);

if current < owner.values.len() {
self.current
.fetch_add(1, ::std::sync::atomic::Ordering::Relaxed);
}

Ok(owner.values.len() > current + 1)
}

fn GetMany(&self, values: &mut [T::Default]) -> ::windows::core::Result<u32> {
let owner = ::windows::core::AsImpl::as_impl(&self.owner);
let current = self.current.load(::std::sync::atomic::Ordering::Relaxed);

let actual = std::cmp::min(owner.values.len() - current, values.len());
let (values, _) = values.split_at_mut(actual);
values.clone_from_slice(&owner.values[current..current + actual]);
self.current
.fetch_add(actual, ::std::sync::atomic::Ordering::Relaxed);
Ok(actual as _)
}
}

impl<T> ::core::convert::TryFrom<::std::vec::Vec<T::Default>> for IIterable<T>
where
T: ::windows::core::RuntimeType,
<T as ::windows::core::Type<T>>::Default: ::std::clone::Clone,
{
type Error = ::windows::core::Error;
fn try_from(values: ::std::vec::Vec<T::Default>) -> ::windows::core::Result<Self> {
// TODO: should provide a fallible try_into or more explicit allocator
Ok(Iterable { values }.into())
}
}
8 changes: 6 additions & 2 deletions crates/libs/bindgen/src/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ pub fn gen_mod(gen: &Gen, namespace: &str) -> TokenStream {
.into()
}

pub fn gen_impl(_namespace: &str) -> TokenStream {
TokenStream::new()
pub fn gen_impl(namespace: &str) -> TokenStream {
match namespace {
"Windows.Foundation.Collections" => include_str!("impl/Foundation/Collections/Iterable.rs"),
_ => "",
}
.into()
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ impl Matrix3x2 {
pub x: f32,
pub y: f32,
}
::windows::core::link!("d2d1.dll" "system" fn D2D1MakeRotateMatrix(angle: f32, center: D2D_POINT_2F, matrix: *mut Matrix3x2) -> ());
::windows::imp::link!("d2d1.dll" "system" fn D2D1MakeRotateMatrix(angle: f32, center: D2D_POINT_2F, matrix: *mut Matrix3x2) -> ());
let mut matrix = Self::default();
unsafe {
D2D1MakeRotateMatrix(angle, D2D_POINT_2F { x, y }, &mut matrix);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl Matrix4x4 {
}
}
pub fn rotation_y(degree: f32) -> Self {
::windows::core::link!("d2d1.dll" "system" fn D2D1SinCos(angle: f32, sin: *mut f32, cos: *mut f32) -> ());
::windows::imp::link!("d2d1.dll" "system" fn D2D1SinCos(angle: f32, sin: *mut f32, cos: *mut f32) -> ());
let angle = degree * (3.141592654 / 180.0);
let mut sin = 0.0;
let mut cos = 0.0;
Expand Down
4 changes: 2 additions & 2 deletions crates/libs/bindgen/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {

if gen.namespace.starts_with("Windows.") {
quote! {
::windows::core::link!(#link #extern_abi fn #name(#(#abi_params),*) #abi_return_type);
::windows::imp::link!(#link #extern_abi fn #name(#(#abi_params),*) #abi_return_type);
}
} else {
let link = link.trim_end_matches(".dll");
Expand Down Expand Up @@ -206,7 +206,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause {
#link
let result__ = #name(#args);
::windows::core::then(!result__.is_invalid(), ||result__).ok_or_else(::windows::core::Error::from_win32)
::windows::imp::then(!result__.is_invalid(), ||result__).ok_or_else(::windows::core::Error::from_win32)
}
}
} else {
Expand Down
10 changes: 5 additions & 5 deletions crates/libs/bindgen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ impl<'a> Gen<'a> {
impl<#constraints> #ident {
pub fn get(&self) -> ::windows::core::Result<#return_type> {
if self.Status()? == #namespace AsyncStatus::Started {
let (_waiter, signaler) = ::windows::core::Waiter::new()?;
let (_waiter, signaler) = ::windows::imp::Waiter::new()?;
self.SetCompleted(&#namespace #handler::new(move |_sender, _args| {
// Safe because the waiter will only be dropped after being signaled.
unsafe { signaler.signal(); }
Expand Down Expand Up @@ -689,14 +689,14 @@ impl<'a> Gen<'a> {
let type_signature = if self.reader.type_def_kind(def) == TypeKind::Class {
let type_signature =
Literal::byte_string(self.reader.type_def_signature(def, generics).as_bytes());
quote! { ::windows::core::ConstBuffer::from_slice(#type_signature) }
quote! { ::windows::imp::ConstBuffer::from_slice(#type_signature) }
} else {
let signature = Literal::byte_string(
format!("{{{:#?}}}", self.reader.type_def_guid(def).unwrap()).as_bytes(),
);

if generics.is_empty() {
quote! { ::windows::core::ConstBuffer::from_slice(#signature) }
quote! { ::windows::imp::ConstBuffer::from_slice(#signature) }
} else {
let generics = generics.iter().enumerate().map(|(index, g)| {
let g = self.type_name(g);
Expand All @@ -716,7 +716,7 @@ impl<'a> Gen<'a> {

quote! {
{
::windows::core::ConstBuffer::new()
::windows::imp::ConstBuffer::new()
.push_slice(b"pinterface(")
.push_slice(#signature)
.push_slice(b";")
Expand All @@ -730,7 +730,7 @@ impl<'a> Gen<'a> {
quote! {
#features
impl<#constraints> ::windows::core::RuntimeType for #ident {
const SIGNATURE: ::windows::core::ConstBuffer = #type_signature;
const SIGNATURE: ::windows::imp::ConstBuffer = #type_signature;
}
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion crates/libs/bindgen/src/interfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream {
});

if !vtables.is_empty() && generics.is_empty() {
let mut hierarchy = format!("::windows::core::interface_hierarchy!({ident}");
let mut hierarchy = format!("::windows::imp::interface_hierarchy!({ident}");
let mut hierarchy_cfg = cfg.clone();

for ty in &vtables {
Expand Down
2 changes: 1 addition & 1 deletion crates/libs/bindgen/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ fn gen_windows_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) ->
tokens.combine(&quote! {
#features
impl ::windows::core::RuntimeType for #name {
const SIGNATURE: ::windows::core::ConstBuffer = ::windows::core::ConstBuffer::from_slice(#signature);
const SIGNATURE: ::windows::imp::ConstBuffer = ::windows::imp::ConstBuffer::from_slice(#signature);
}
});
}
Expand Down
6 changes: 3 additions & 3 deletions crates/libs/implement/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro:
identity: *const ::windows::core::IInspectable_Vtbl,
vtables: (#(*const #vtbl_idents,)*),
this: #original_ident::<#(#generics,)*>,
count: ::windows::core::WeakRefCount,
count: ::windows::imp::WeakRefCount,
}
impl <#(#generics,)*> #impl_ident::<#(#generics,)*> where #constraints {
const VTABLES: (#(#vtbl_idents2,)*) = (#(#vtable_news,)*);
Expand All @@ -88,7 +88,7 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro:
identity: &Self::IDENTITY,
vtables:(#(&Self::VTABLES.#offset,)*),
this,
count: ::windows::core::WeakRefCount::new(),
count: ::windows::imp::WeakRefCount::new(),
}
}
}
Expand All @@ -101,7 +101,7 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro:
unsafe {
*interface = if iid == &<::windows::core::IUnknown as ::windows::core::Interface>::IID
|| iid == &<::windows::core::IInspectable as ::windows::core::Interface>::IID
|| iid == &<::windows::core::IAgileObject as ::windows::core::Interface>::IID {
|| iid == &<::windows::imp::IAgileObject as ::windows::core::Interface>::IID {
&self.identity as *const _ as *const _
} #(#queries)* else {
::core::ptr::null_mut()
Expand Down
Loading