summaryrefslogtreecommitdiff
path: root/vendor/windows-implement
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/windows-implement
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/windows-implement')
-rw-r--r--vendor/windows-implement/.cargo-checksum.json1
-rw-r--r--vendor/windows-implement/Cargo.lock47
-rw-r--r--vendor/windows-implement/Cargo.toml70
-rw-r--r--vendor/windows-implement/license-apache-2.0201
-rw-r--r--vendor/windows-implement/license-mit21
-rw-r--r--vendor/windows-implement/src/gen.rs587
-rw-r--r--vendor/windows-implement/src/lib.rs383
-rw-r--r--vendor/windows-implement/src/tests.rs135
8 files changed, 1445 insertions, 0 deletions
diff --git a/vendor/windows-implement/.cargo-checksum.json b/vendor/windows-implement/.cargo-checksum.json
new file mode 100644
index 00000000..f616b8a3
--- /dev/null
+++ b/vendor/windows-implement/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"07ffe21585cb9601285232fa32088f8ac8a419e3e2c8a19d5479ca4ab6bb75c7","Cargo.toml":"4dab9cdda3e2a5cf3b4212f42b3ddcba34ecb766ffc0bd3449264289165aa73f","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/gen.rs":"e7e4cbeb1f685af8f2c1843d6064008fdc7610ebdda2657cded8beb59ecdf9b7","src/lib.rs":"94f2d415896df707932fe8da9dbba0844319f24cb1951526ce553fde47717e57","src/tests.rs":"ea34a27316c2c7440bdc41d03fa7a3426be344a238588d3728b490a44bfecc2e"},"package":"a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"} \ No newline at end of file
diff --git a/vendor/windows-implement/Cargo.lock b/vendor/windows-implement/Cargo.lock
new file mode 100644
index 00000000..88fdf819
--- /dev/null
+++ b/vendor/windows-implement/Cargo.lock
@@ -0,0 +1,47 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "windows-implement"
+version = "0.60.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/vendor/windows-implement/Cargo.toml b/vendor/windows-implement/Cargo.toml
new file mode 100644
index 00000000..270b2f6e
--- /dev/null
+++ b/vendor/windows-implement/Cargo.toml
@@ -0,0 +1,70 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.74"
+name = "windows-implement"
+version = "0.60.0"
+authors = ["Microsoft"]
+build = false
+autolib = false
+autobins = false
+autoexamples = false
+autotests = false
+autobenches = false
+description = "The implement macro for the windows crate"
+readme = false
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/microsoft/windows-rs"
+
+[package.metadata.docs.rs]
+default-target = "x86_64-pc-windows-msvc"
+targets = []
+
+[lib]
+name = "windows_implement"
+path = "src/lib.rs"
+proc-macro = true
+
+[dependencies.proc-macro2]
+version = "1.0"
+default-features = false
+
+[dependencies.quote]
+version = "1.0"
+default-features = false
+
+[dependencies.syn]
+version = "2.0"
+features = [
+ "parsing",
+ "proc-macro",
+ "printing",
+ "full",
+ "clone-impls",
+]
+default-features = false
+
+[dev-dependencies]
+
+[lints.rust]
+missing_docs = "warn"
+unsafe_op_in_unsafe_fn = "warn"
+
+[lints.rust.rust_2018_idioms]
+level = "warn"
+priority = -1
+
+[lints.rust.unexpected_cfgs]
+level = "warn"
+priority = 0
+check-cfg = ["cfg(windows_raw_dylib, windows_debugger_visualizer, windows_slim_errors)"]
diff --git a/vendor/windows-implement/license-apache-2.0 b/vendor/windows-implement/license-apache-2.0
new file mode 100644
index 00000000..b5ed4ece
--- /dev/null
+++ b/vendor/windows-implement/license-apache-2.0
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright (c) Microsoft Corporation.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/windows-implement/license-mit b/vendor/windows-implement/license-mit
new file mode 100644
index 00000000..9e841e7a
--- /dev/null
+++ b/vendor/windows-implement/license-mit
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/vendor/windows-implement/src/gen.rs b/vendor/windows-implement/src/gen.rs
new file mode 100644
index 00000000..56253b99
--- /dev/null
+++ b/vendor/windows-implement/src/gen.rs
@@ -0,0 +1,587 @@
+//! Generates output for the `implement` proc macro.
+//!
+//! Each function in this module focuses on generating one thing, or one kind of thing.
+//! Each takes `ImplementInputs` as its input. `gen_all` calls all of the `gen_*` functions
+//! and merges them into the final list of output items.
+//!
+//! We use `parse_quote` so that we can verify that a given function generates a well-formed AST
+//! item, within the narrowest possible scope. This allows us to detect errors more quickly during
+//! development. If the input to `parse_quote` cannot be parsed, then the macro will panic and
+//! the panic will point to the specific `parse_quote` call, rather than the entire output of the
+//! `implement` proc macro being unparsable. This greatly aids in development.
+
+use super::*;
+use quote::{quote, quote_spanned};
+use syn::{parse_quote, parse_quote_spanned};
+
+/// Generates code for the `#[implements]` macro.
+pub(crate) fn gen_all(inputs: &ImplementInputs) -> Vec<syn::Item> {
+ let mut items: Vec<syn::Item> = Vec::with_capacity(64);
+
+ items.push(gen_original_impl(inputs));
+ items.push(gen_impl_struct(inputs));
+ items.push(gen_impl_deref(inputs));
+ items.push(gen_impl_impl(inputs));
+ items.push(gen_iunknown_impl(inputs));
+ items.push(gen_impl_com_object_inner(inputs));
+ items.extend(gen_impl_from(inputs));
+ items.extend(gen_impl_com_object_interfaces(inputs));
+
+ for (i, interface_chain) in inputs.interface_chains.iter().enumerate() {
+ items.push(gen_impl_as_impl(inputs, interface_chain, i));
+ }
+
+ items
+}
+
+/// Generates an `impl` block for the original `Foo` type.
+///
+/// This `impl` block will contain `into_outer` and `into_static` (if applicable).
+fn gen_original_impl(inputs: &ImplementInputs) -> syn::Item {
+ let original_ident = &inputs.original_ident;
+ let generics = &inputs.generics;
+ let constraints = &inputs.constraints;
+
+ let mut output: syn::ItemImpl = parse_quote! {
+ impl #generics #original_ident::#generics where #constraints {}
+ };
+
+ output.items.push(gen_into_outer(inputs));
+
+ // Static COM objects have a lot of constraints. They can't be generic (open parameters),
+ // because that would be meaningless (an open generic type cannot have a known representation).
+ //
+ // Right now, we can't generate static COM objects that have base classes because we rely on
+ // boxing and then unboxing during construction of aggregated types.
+ if !inputs.is_generic {
+ output.items.push(gen_into_static(inputs));
+ }
+
+ syn::Item::Impl(output)
+}
+
+/// Generates the structure definition for the `Foo_Impl` type.
+fn gen_impl_struct(inputs: &ImplementInputs) -> syn::Item {
+ let impl_ident = &inputs.impl_ident;
+ let generics = &inputs.generics;
+ let constraints = &inputs.constraints;
+ let original_ident = &inputs.original_ident;
+ let vis = &inputs.original_type.vis;
+
+ let mut impl_fields = quote! {
+ identity: &'static ::windows_core::IInspectable_Vtbl,
+ };
+
+ for interface_chain in inputs.interface_chains.iter() {
+ let vtbl_ty = interface_chain.implement.to_vtbl_ident();
+ let chain_field_ident = &interface_chain.field_ident;
+ impl_fields.extend(quote! {
+ #chain_field_ident: &'static #vtbl_ty,
+ });
+ }
+
+ impl_fields.extend(quote! {
+ this: #original_ident::#generics,
+ count: ::windows_core::imp::WeakRefCount,
+ });
+
+ parse_quote! {
+ #[repr(C)]
+ #[allow(non_camel_case_types)]
+ #vis struct #impl_ident #generics where #constraints {
+ #impl_fields
+ }
+ }
+}
+
+/// Generates the implementation of `core::ops::Deref` for the generated `Foo_Impl` type.
+fn gen_impl_deref(inputs: &ImplementInputs) -> syn::Item {
+ let generics = &inputs.generics;
+ let constraints = &inputs.constraints;
+ let original_ident = &inputs.original_type.ident;
+ let impl_ident = &inputs.impl_ident;
+
+ parse_quote! {
+ impl #generics ::core::ops::Deref for #impl_ident::#generics where #constraints {
+ type Target = #original_ident::#generics;
+
+ #[inline(always)]
+ fn deref(&self) -> &Self::Target {
+ &self.this
+ }
+ }
+ }
+}
+
+/// Generates an `impl` block for the generated `Foo_Impl` block.
+///
+/// This generates:
+///
+/// ```rust,ignore
+/// const VTABLE_IDENTITY = IInspectable_Vtbl = ...;
+/// const VTABLE_INTERFACE1_IFOO: IFoo_Vtbl = ...;
+/// const VTABLE_INTERFACE2_IBAR: IBar_Vtbl = ...;
+/// ```
+///
+/// These constants are used when constructing vtables. The benefit of using constants instead
+/// of directly generating these expressions is that it allows us to overcome limitations in
+/// using generics in constant contexts. Right now, Rust has a lot of limitations around using
+/// constants in constant contexts. Fortunately, associated constants (constants defined within
+/// `impl` blocks) work in stable Rust, even for generic types.
+fn gen_impl_impl(inputs: &ImplementInputs) -> syn::Item {
+ let impl_ident = &inputs.impl_ident;
+ let generics = &inputs.generics;
+ let constraints = &inputs.constraints;
+
+ let mut output: syn::ItemImpl = parse_quote! {
+ impl #generics #impl_ident::#generics where #constraints {}
+ };
+
+ // This is here so that IInspectable::GetRuntimeClassName can work properly.
+ // For a test case for this, see crates/tests/misc/component_client.
+ let identity_type = if let Some(first) = inputs.interface_chains.first() {
+ first.implement.to_ident()
+ } else {
+ quote! { ::windows_core::IInspectable }
+ };
+
+ output.items.push(parse_quote! {
+ const VTABLE_IDENTITY: ::windows_core::IInspectable_Vtbl =
+ ::windows_core::IInspectable_Vtbl::new::<
+ #impl_ident::#generics,
+ #identity_type,
+ 0,
+ >();
+ });
+
+ for (interface_index, interface_chain) in inputs.interface_chains.iter().enumerate() {
+ let vtbl_ty = interface_chain.implement.to_vtbl_ident();
+ let vtable_const_ident = &interface_chain.vtable_const_ident;
+
+ let chain_offset_in_pointers: isize = -1 - interface_index as isize;
+ output.items.push(parse_quote! {
+ const #vtable_const_ident: #vtbl_ty = #vtbl_ty::new::<
+ #impl_ident::#generics,
+ #chain_offset_in_pointers,
+ >();
+ });
+ }
+
+ syn::Item::Impl(output)
+}
+
+/// Generates the `IUnknownImpl` implementation for the `Foo_Impl` type.
+fn gen_iunknown_impl(inputs: &ImplementInputs) -> syn::Item {
+ let generics = &inputs.generics;
+ let constraints = &inputs.constraints;
+ let impl_ident = &inputs.impl_ident;
+ let original_ident = &inputs.original_type.ident;
+
+ let trust_level = proc_macro2::Literal::usize_unsuffixed(inputs.trust_level);
+
+ let mut output: syn::ItemImpl = parse_quote! {
+ impl #generics ::windows_core::IUnknownImpl for #impl_ident::#generics where #constraints {
+ type Impl = #original_ident::#generics;
+
+ #[inline(always)]
+ fn get_impl(&self) -> &Self::Impl {
+ &self.this
+ }
+
+ #[inline(always)]
+ fn get_impl_mut(&mut self) -> &mut Self::Impl {
+ &mut self.this
+ }
+
+ #[inline(always)]
+ fn into_inner(self) -> Self::Impl {
+ self.this
+ }
+
+ #[inline(always)]
+ fn AddRef(&self) -> u32 {
+ self.count.add_ref()
+ }
+
+ #[inline(always)]
+ unsafe fn Release(self_: *mut Self) -> u32 {
+ let remaining = (*self_).count.release();
+ if remaining == 0 {
+ _ = ::windows_core::imp::Box::from_raw(self_);
+ }
+ remaining
+ }
+
+ #[inline(always)]
+ fn is_reference_count_one(&self) -> bool {
+ self.count.is_one()
+ }
+
+ unsafe fn GetTrustLevel(&self, value: *mut i32) -> ::windows_core::HRESULT {
+ if value.is_null() {
+ return ::windows_core::imp::E_POINTER;
+ }
+ *value = #trust_level;
+ ::windows_core::HRESULT(0)
+ }
+
+ fn to_object(&self) -> ::windows_core::ComObject<Self::Impl> {
+ self.count.add_ref();
+ unsafe {
+ ::windows_core::ComObject::from_raw(
+ ::core::ptr::NonNull::new_unchecked(self as *const Self as *mut Self)
+ )
+ }
+ }
+ }
+ };
+
+ let query_interface_fn = gen_query_interface(inputs);
+ output.items.push(syn::ImplItem::Fn(query_interface_fn));
+
+ syn::Item::Impl(output)
+}
+
+/// Generates the implementation of `ComObjectInner`.
+fn gen_impl_com_object_inner(inputs: &ImplementInputs) -> syn::Item {
+ let original_ident = &inputs.original_type.ident;
+ let generics = &inputs.generics;
+ let constraints = &inputs.constraints;
+ let impl_ident = &inputs.impl_ident;
+
+ parse_quote! {
+ impl #generics ::windows_core::ComObjectInner for #original_ident::#generics where #constraints {
+ type Outer = #impl_ident::#generics;
+
+ // IMPORTANT! This function handles assembling the "boxed" type of a COM object.
+ // It immediately moves the box into a heap allocation (box) and returns only a ComObject
+ // reference that points to it. We intentionally _do not_ expose any owned instances of
+ // Foo_Impl to safe Rust code, because doing so would allow unsound behavior in safe Rust
+ // code, due to the adjustments of the reference count that Foo_Impl permits.
+ //
+ // This is why this function returns ComObject<Self> instead of returning #impl_ident.
+
+ fn into_object(self) -> ::windows_core::ComObject<Self> {
+ let boxed = ::windows_core::imp::Box::<#impl_ident::#generics>::new(self.into_outer());
+ unsafe {
+ let ptr = ::windows_core::imp::Box::into_raw(boxed);
+ ::windows_core::ComObject::from_raw(
+ ::core::ptr::NonNull::new_unchecked(ptr)
+ )
+ }
+ }
+ }
+ }
+}
+
+/// Generates the `query_interface` method.
+fn gen_query_interface(inputs: &ImplementInputs) -> syn::ImplItemFn {
+ let queries = inputs.interface_chains.iter().map(|interface_chain| {
+ let chain_ty = interface_chain.implement.to_vtbl_ident();
+ let chain_field = &interface_chain.field_ident;
+ quote_spanned! {
+ interface_chain.implement.span =>
+ if #chain_ty::matches(&iid) {
+ break 'found &self.#chain_field as *const _ as *const ::core::ffi::c_void;
+ }
+ }
+ });
+
+ // Dynamic casting requires that the object not contain non-static lifetimes.
+ let enable_dyn_casting = inputs.original_type.generics.lifetimes().count() == 0;
+ let dynamic_cast_query = if enable_dyn_casting {
+ quote! {
+ if iid == ::windows_core::DYNAMIC_CAST_IID {
+ // DYNAMIC_CAST_IID is special. We _do not_ increase the reference count for this pseudo-interface.
+ // Also, instead of returning an interface pointer, we simply write the `&dyn Any` directly to the
+ // 'interface' pointer. Since the size of `&dyn Any` is 2 pointers, not one, the caller must be
+ // prepared for this. This is not a normal QueryInterface call.
+ //
+ // See the `Interface::cast_to_any` method, which is the only caller that should use DYNAMIC_CAST_ID.
+ (interface as *mut *const dyn core::any::Any).write(self as &dyn ::core::any::Any as *const dyn ::core::any::Any);
+ return ::windows_core::HRESULT(0);
+ }
+ }
+ } else {
+ quote!()
+ };
+
+ let identity_query = quote! {
+ if iid == <::windows_core::IUnknown as ::windows_core::Interface>::IID
+ || iid == <::windows_core::IInspectable as ::windows_core::Interface>::IID
+ || iid == <::windows_core::imp::IAgileObject as ::windows_core::Interface>::IID {
+ break 'found &self.identity as *const _ as *const ::core::ffi::c_void;
+ }
+ };
+
+ let marshal_query = quote! {
+ #[cfg(windows)]
+ if iid == <::windows_core::imp::IMarshal as ::windows_core::Interface>::IID {
+ return ::windows_core::imp::marshaler(self.to_interface(), interface);
+ }
+ };
+
+ let tear_off_query = quote! {
+ let tear_off_ptr = self.count.query(&iid, &self.identity as *const _ as *mut _);
+ if !tear_off_ptr.is_null() {
+ *interface = tear_off_ptr;
+ return ::windows_core::HRESULT(0);
+ }
+ };
+
+ parse_quote! {
+ unsafe fn QueryInterface(
+ &self,
+ iid: *const ::windows_core::GUID,
+ interface: *mut *mut ::core::ffi::c_void,
+ ) -> ::windows_core::HRESULT {
+ unsafe {
+ if iid.is_null() || interface.is_null() {
+ return ::windows_core::imp::E_POINTER;
+ }
+
+ let iid = *iid;
+
+ let interface_ptr: *const ::core::ffi::c_void = 'found: {
+ #identity_query
+ #(#queries)*
+ #marshal_query
+ #dynamic_cast_query
+ #tear_off_query
+
+ *interface = ::core::ptr::null_mut();
+ return ::windows_core::imp::E_NOINTERFACE;
+ };
+
+ debug_assert!(!interface_ptr.is_null());
+ *interface = interface_ptr as *mut ::core::ffi::c_void;
+ self.count.add_ref();
+ return ::windows_core::HRESULT(0);
+ }
+ }
+ }
+}
+
+/// Generates the `T::into_outer` function. This function is part of how we construct a
+/// `ComObject<T>` from a `T`.
+fn gen_into_outer(inputs: &ImplementInputs) -> syn::ImplItem {
+ let generics = &inputs.generics;
+ let impl_ident = &inputs.impl_ident;
+
+ let mut initializers = quote! {
+ identity: &#impl_ident::#generics::VTABLE_IDENTITY,
+ };
+
+ for interface_chain in inputs.interface_chains.iter() {
+ let vtbl_field_ident = &interface_chain.field_ident;
+ let vtable_const_ident = &interface_chain.vtable_const_ident;
+
+ initializers.extend(quote_spanned! {
+ interface_chain.implement.span =>
+ #vtbl_field_ident: &#impl_ident::#generics::#vtable_const_ident,
+ });
+ }
+
+ // If the type is generic then into_outer() cannot be a const fn.
+ let maybe_const = if inputs.is_generic {
+ quote!()
+ } else {
+ quote!(const)
+ };
+
+ parse_quote! {
+ // This constructs an "outer" object. This should only be used by the implementation
+ // of the outer object, never by application code.
+ //
+ // The callers of this function (`into_static` and `into_object`) are both responsible
+ // for maintaining one of our invariants: Application code never has an owned instance
+ // of the outer (implementation) type. into_static() maintains this invariant by
+ // returning a wrapped StaticComObject value, which owns its contents but never gives
+ // application code a way to mutably access its contents. This prevents the refcount
+ // shearing problem.
+ //
+ // TODO: Make it impossible for app code to call this function, by placing it in a
+ // module and marking this as private to the module.
+ #[inline(always)]
+ #maybe_const fn into_outer(self) -> #impl_ident::#generics {
+ #impl_ident::#generics {
+ #initializers
+ count: ::windows_core::imp::WeakRefCount::new(),
+ this: self,
+ }
+ }
+ }
+}
+
+/// Generates the `T::into_static` function. This function is part of how we construct a
+/// `StaticComObject<T>` from a `T`.
+fn gen_into_static(inputs: &ImplementInputs) -> syn::ImplItem {
+ assert!(!inputs.is_generic);
+ parse_quote! {
+ /// This converts a partially-constructed COM object (in the sense that it contains
+ /// application state but does not yet have vtable and reference count constructed)
+ /// into a `StaticComObject`. This allows the COM object to be stored in static
+ /// (global) variables.
+ pub const fn into_static(self) -> ::windows_core::StaticComObject<Self> {
+ ::windows_core::StaticComObject::from_outer(self.into_outer())
+ }
+ }
+}
+
+/// Generates `From`-based conversions.
+///
+/// These conversions convert from the user's type `T` to `ComObject<T>` or to an interface
+/// implemented by `T`. These conversions are shorthand for calling `ComObject::new(value)`.
+///
+/// We can only generate conversions from `T` to the roots of each interface chain. We can't
+/// generate `From` conversions from `T` to an interface that is inherited by an interface chain,
+/// because this proc macro does not have access to any information about the inheritance chain
+/// of interfaces that are referenced.
+///
+/// For example:
+///
+/// ```rust,ignore
+/// #[implement(IFoo3)]
+/// struct MyType;
+/// ```
+///
+/// If `IFoo3` inherits from `IFoo2`, then this code will _not_ generate a conversion for `IFoo2`.
+/// However, user code can still do this:
+///
+/// ```rust,ignore
+/// let ifoo2 = IFoo3::from(MyType).into();
+/// ```
+///
+/// This works because the `IFoo3` type has an `Into` impl for `IFoo2`.
+fn gen_impl_from(inputs: &ImplementInputs) -> Vec<syn::Item> {
+ let mut items = Vec::new();
+
+ let original_ident = &inputs.original_type.ident;
+ let generics = &inputs.generics;
+ let constraints = &inputs.constraints;
+
+ items.push(parse_quote! {
+ impl #generics ::core::convert::From<#original_ident::#generics> for ::windows_core::IUnknown where #constraints {
+ #[inline(always)]
+ fn from(this: #original_ident::#generics) -> Self {
+ let com_object = ::windows_core::ComObject::new(this);
+ com_object.into_interface()
+ }
+ }
+ });
+
+ items.push(parse_quote! {
+ impl #generics ::core::convert::From<#original_ident::#generics> for ::windows_core::IInspectable where #constraints {
+ #[inline(always)]
+ fn from(this: #original_ident::#generics) -> Self {
+ let com_object = ::windows_core::ComObject::new(this);
+ com_object.into_interface()
+ }
+ }
+ });
+
+ for interface_chain in inputs.interface_chains.iter() {
+ let interface_ident = interface_chain.implement.to_ident();
+
+ items.push(parse_quote_spanned! {
+ interface_chain.implement.span =>
+ impl #generics ::core::convert::From<#original_ident::#generics> for #interface_ident where #constraints {
+ #[inline(always)]
+ fn from(this: #original_ident::#generics) -> Self {
+ let com_object = ::windows_core::ComObject::new(this);
+ com_object.into_interface()
+ }
+ }
+ });
+ }
+
+ items
+}
+
+/// Generates the `ComObjectInterface` implementation for each interface chain.
+///
+/// Each of these `impl` blocks says "this COM object implements this COM interface".
+/// It allows the `ComObject` type to do conversions from the `ComObject` to `IFoo` instances,
+/// _without_ doing a `QueryInterface` call.
+fn gen_impl_com_object_interfaces(inputs: &ImplementInputs) -> Vec<syn::Item> {
+ let mut items = Vec::new();
+
+ let generics = &inputs.generics;
+ let constraints = &inputs.constraints;
+ let impl_ident = &inputs.impl_ident;
+
+ items.push(parse_quote! {
+ impl #generics ::windows_core::ComObjectInterface<::windows_core::IUnknown> for #impl_ident::#generics where #constraints {
+ #[inline(always)]
+ fn as_interface_ref(&self) -> ::windows_core::InterfaceRef<'_, ::windows_core::IUnknown> {
+ unsafe {
+ let interface_ptr = &self.identity;
+ ::core::mem::transmute(interface_ptr)
+ }
+ }
+ }
+ });
+
+ items.push(parse_quote! {
+ impl #generics ::windows_core::ComObjectInterface<::windows_core::IInspectable> for #impl_ident::#generics where #constraints {
+ #[inline(always)]
+ fn as_interface_ref(&self) -> ::windows_core::InterfaceRef<'_, ::windows_core::IInspectable> {
+ unsafe {
+ let interface_ptr = &self.identity;
+ ::core::mem::transmute(interface_ptr)
+ }
+ }
+ }
+ });
+
+ for interface_chain in inputs.interface_chains.iter() {
+ let chain_field = &interface_chain.field_ident;
+ let interface_ident = interface_chain.implement.to_ident();
+
+ items.push(parse_quote_spanned! {
+ interface_chain.implement.span =>
+ #[allow(clippy::needless_lifetimes)]
+ impl #generics ::windows_core::ComObjectInterface<#interface_ident> for #impl_ident::#generics where #constraints {
+ #[inline(always)]
+ fn as_interface_ref(&self) -> ::windows_core::InterfaceRef<'_, #interface_ident> {
+ unsafe {
+ ::core::mem::transmute(&self.#chain_field)
+ }
+ }
+ }
+ });
+ }
+
+ items
+}
+
+/// Generates the implementation of the `AsImpl` trait for a given interface chain.
+fn gen_impl_as_impl(
+ inputs: &ImplementInputs,
+ interface_chain: &InterfaceChain,
+ interface_chain_index: usize,
+) -> syn::Item {
+ let generics = &inputs.generics;
+ let constraints = &inputs.constraints;
+ let interface_ident = interface_chain.implement.to_ident();
+ let original_ident = &inputs.original_type.ident;
+ let impl_ident = &inputs.impl_ident;
+
+ parse_quote_spanned! {
+ interface_chain.implement.span =>
+ impl #generics ::windows_core::AsImpl<#original_ident::#generics> for #interface_ident where #constraints {
+ // SAFETY: the offset is guaranteed to be in bounds, and the implementation struct
+ // is guaranteed to live at least as long as `self`.
+ #[inline(always)]
+ unsafe fn as_impl_ptr(&self) -> ::core::ptr::NonNull<#original_ident::#generics> {
+ unsafe {
+ let this = ::windows_core::Interface::as_raw(self);
+ // Subtract away the vtable offset plus 1, for the `identity` field, to get
+ // to the impl struct which contains that original implementation type.
+ let this = (this as *mut *mut ::core::ffi::c_void).sub(1 + #interface_chain_index) as *mut #impl_ident::#generics;
+ ::core::ptr::NonNull::new_unchecked(::core::ptr::addr_of!((*this).this) as *const #original_ident::#generics as *mut #original_ident::#generics)
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/windows-implement/src/lib.rs b/vendor/windows-implement/src/lib.rs
new file mode 100644
index 00000000..c50509af
--- /dev/null
+++ b/vendor/windows-implement/src/lib.rs
@@ -0,0 +1,383 @@
+//! Implement COM interfaces for Rust types.
+//!
+//! Take a look at [macro@implement] for an example.
+//!
+//! Learn more about Rust for Windows here: <https://github.com/microsoft/windows-rs>
+
+use quote::{quote, ToTokens};
+
+mod r#gen;
+use r#gen::gen_all;
+
+#[cfg(test)]
+mod tests;
+
+/// Implements one or more COM interfaces.
+///
+/// # Example
+/// ```rust,no_run
+/// use windows_core::*;
+///
+/// #[interface("094d70d6-5202-44b8-abb8-43860da5aca2")]
+/// unsafe trait IValue: IUnknown {
+/// fn GetValue(&self, value: *mut i32) -> HRESULT;
+/// }
+///
+/// #[implement(IValue)]
+/// struct Value(i32);
+///
+/// impl IValue_Impl for Value_Impl {
+/// unsafe fn GetValue(&self, value: *mut i32) -> HRESULT {
+/// *value = self.0;
+/// HRESULT(0)
+/// }
+/// }
+///
+/// let object: IValue = Value(123).into();
+/// // Call interface methods...
+/// ```
+#[proc_macro_attribute]
+pub fn implement(
+ attributes: proc_macro::TokenStream,
+ type_tokens: proc_macro::TokenStream,
+) -> proc_macro::TokenStream {
+ implement_core(attributes.into(), type_tokens.into()).into()
+}
+
+fn implement_core(
+ attributes: proc_macro2::TokenStream,
+ item_tokens: proc_macro2::TokenStream,
+) -> proc_macro2::TokenStream {
+ let attributes = syn::parse2::<ImplementAttributes>(attributes).unwrap();
+ let original_type = syn::parse2::<syn::ItemStruct>(item_tokens).unwrap();
+
+ // Do a little thinking and assemble ImplementInputs. We pass ImplementInputs to
+ // all of our gen_* function.
+ let inputs = ImplementInputs {
+ original_ident: original_type.ident.clone(),
+ interface_chains: convert_implements_to_interface_chains(attributes.implement),
+ trust_level: attributes.trust_level,
+ impl_ident: quote::format_ident!("{}_Impl", &original_type.ident),
+ constraints: {
+ if let Some(where_clause) = &original_type.generics.where_clause {
+ where_clause.predicates.to_token_stream()
+ } else {
+ quote!()
+ }
+ },
+ generics: if !original_type.generics.params.is_empty() {
+ let mut params = quote! {};
+ original_type.generics.params.to_tokens(&mut params);
+ quote! { <#params> }
+ } else {
+ quote! { <> }
+ },
+ is_generic: !original_type.generics.params.is_empty(),
+ original_type,
+ };
+
+ let items = gen_all(&inputs);
+ let mut tokens = inputs.original_type.into_token_stream();
+ for item in items {
+ tokens.extend(item.into_token_stream());
+ }
+
+ tokens
+}
+
+/// This provides the inputs to the `gen_*` functions, which generate the proc macro output.
+struct ImplementInputs {
+ /// The user's type that was marked with `#[implement]`.
+ original_type: syn::ItemStruct,
+
+ /// The identifier for the user's original type definition.
+ original_ident: syn::Ident,
+
+ /// The list of interface chains that this type implements.
+ interface_chains: Vec<InterfaceChain>,
+
+ /// The "trust level", which is returned by `IInspectable::GetTrustLevel`.
+ trust_level: usize,
+
+ /// The identifier of the `Foo_Impl` type.
+ impl_ident: syn::Ident,
+
+ /// The list of constraints needed for this `Foo_Impl` type.
+ constraints: proc_macro2::TokenStream,
+
+ /// The list of generic parameters for this `Foo_Impl` type, including `<` and `>`.
+ /// If there are no generics, this contains `<>`.
+ generics: proc_macro2::TokenStream,
+
+ /// True if the user type has any generic parameters.
+ is_generic: bool,
+}
+
+/// Describes one COM interface chain.
+struct InterfaceChain {
+ /// The name of the field for the vtable chain, e.g. `interface4_ifoo`.
+ field_ident: syn::Ident,
+
+ /// The name of the associated constant item for the vtable chain's initializer,
+ /// e.g. `INTERFACE4_IFOO_VTABLE`.
+ vtable_const_ident: syn::Ident,
+
+ implement: ImplementType,
+}
+
+struct ImplementType {
+ type_name: String,
+ generics: Vec<ImplementType>,
+
+ /// The best span for diagnostics.
+ span: proc_macro2::Span,
+}
+
+impl ImplementType {
+ fn to_ident(&self) -> proc_macro2::TokenStream {
+ let type_name = syn::parse_str::<proc_macro2::TokenStream>(&self.type_name)
+ .expect("Invalid token stream");
+ let generics = self.generics.iter().map(|g| g.to_ident());
+ quote! { #type_name<#(#generics,)*> }
+ }
+ fn to_vtbl_ident(&self) -> proc_macro2::TokenStream {
+ let ident = self.to_ident();
+ quote! {
+ <#ident as ::windows_core::Interface>::Vtable
+ }
+ }
+}
+
+#[derive(Default)]
+struct ImplementAttributes {
+ pub implement: Vec<ImplementType>,
+ pub trust_level: usize,
+}
+
+impl syn::parse::Parse for ImplementAttributes {
+ fn parse(cursor: syn::parse::ParseStream<'_>) -> syn::parse::Result<Self> {
+ let mut input = Self::default();
+
+ while !cursor.is_empty() {
+ input.parse_implement(cursor)?;
+ }
+
+ Ok(input)
+ }
+}
+
+impl ImplementAttributes {
+ fn parse_implement(&mut self, cursor: syn::parse::ParseStream<'_>) -> syn::parse::Result<()> {
+ let tree = cursor.parse::<UseTree2>()?;
+ self.walk_implement(&tree, &mut String::new())?;
+
+ if !cursor.is_empty() {
+ cursor.parse::<syn::Token![,]>()?;
+ }
+
+ Ok(())
+ }
+
+ fn walk_implement(
+ &mut self,
+ tree: &UseTree2,
+ namespace: &mut String,
+ ) -> syn::parse::Result<()> {
+ match tree {
+ UseTree2::Path(input) => {
+ if !namespace.is_empty() {
+ namespace.push_str("::");
+ }
+
+ namespace.push_str(&input.ident.to_string());
+ self.walk_implement(&input.tree, namespace)?;
+ }
+ UseTree2::Name(_) => {
+ self.implement.push(tree.to_element_type(namespace)?);
+ }
+ UseTree2::Group(input) => {
+ for tree in &input.items {
+ self.walk_implement(tree, namespace)?;
+ }
+ }
+ UseTree2::TrustLevel(input) => self.trust_level = *input,
+ }
+
+ Ok(())
+ }
+}
+
+enum UseTree2 {
+ Path(UsePath2),
+ Name(UseName2),
+ Group(UseGroup2),
+ TrustLevel(usize),
+}
+
+impl UseTree2 {
+ fn to_element_type(&self, namespace: &mut String) -> syn::parse::Result<ImplementType> {
+ match self {
+ UseTree2::Path(input) => {
+ if !namespace.is_empty() {
+ namespace.push_str("::");
+ }
+
+ namespace.push_str(&input.ident.to_string());
+ input.tree.to_element_type(namespace)
+ }
+ UseTree2::Name(input) => {
+ let mut type_name = input.ident.to_string();
+ let span = input.ident.span();
+
+ if !namespace.is_empty() {
+ type_name = format!("{namespace}::{type_name}");
+ }
+
+ let mut generics = vec![];
+
+ for g in &input.generics {
+ generics.push(g.to_element_type(&mut String::new())?);
+ }
+
+ Ok(ImplementType {
+ type_name,
+ generics,
+ span,
+ })
+ }
+ UseTree2::Group(input) => Err(syn::parse::Error::new(
+ input.brace_token.span.join(),
+ "Syntax not supported",
+ )),
+ _ => unimplemented!(),
+ }
+ }
+}
+
+struct UsePath2 {
+ pub ident: syn::Ident,
+ pub tree: Box<UseTree2>,
+}
+
+struct UseName2 {
+ pub ident: syn::Ident,
+ pub generics: Vec<UseTree2>,
+}
+
+struct UseGroup2 {
+ pub brace_token: syn::token::Brace,
+ pub items: syn::punctuated::Punctuated<UseTree2, syn::Token![,]>,
+}
+
+impl syn::parse::Parse for UseTree2 {
+ fn parse(input: syn::parse::ParseStream<'_>) -> syn::parse::Result<UseTree2> {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(syn::Ident) {
+ use syn::ext::IdentExt;
+ let ident = input.call(syn::Ident::parse_any)?;
+ if input.peek(syn::Token![::]) {
+ input.parse::<syn::Token![::]>()?;
+ Ok(UseTree2::Path(UsePath2 {
+ ident,
+ tree: Box::new(input.parse()?),
+ }))
+ } else if input.peek(syn::Token![=]) {
+ if ident != "TrustLevel" {
+ return Err(syn::parse::Error::new(
+ ident.span(),
+ "Unrecognized key-value pair",
+ ));
+ }
+ input.parse::<syn::Token![=]>()?;
+ let span = input.span();
+ let value = input.call(syn::Ident::parse_any)?;
+ match value.to_string().as_str() {
+ "Partial" => Ok(UseTree2::TrustLevel(1)),
+ "Full" => Ok(UseTree2::TrustLevel(2)),
+ _ => Err(syn::parse::Error::new(
+ span,
+ "`TrustLevel` must be `Partial` or `Full`",
+ )),
+ }
+ } else {
+ let generics = if input.peek(syn::Token![<]) {
+ input.parse::<syn::Token![<]>()?;
+ let mut generics = Vec::new();
+ loop {
+ generics.push(input.parse::<UseTree2>()?);
+
+ if input.parse::<syn::Token![,]>().is_err() {
+ break;
+ }
+ }
+ input.parse::<syn::Token![>]>()?;
+ generics
+ } else {
+ Vec::new()
+ };
+
+ Ok(UseTree2::Name(UseName2 { ident, generics }))
+ }
+ } else if lookahead.peek(syn::token::Brace) {
+ let content;
+ let brace_token = syn::braced!(content in input);
+ let items = content.parse_terminated(UseTree2::parse, syn::Token![,])?;
+
+ Ok(UseTree2::Group(UseGroup2 { brace_token, items }))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+}
+
+fn convert_implements_to_interface_chains(implements: Vec<ImplementType>) -> Vec<InterfaceChain> {
+ let mut chains = Vec::with_capacity(implements.len());
+
+ for (i, implement) in implements.into_iter().enumerate() {
+ // Create an identifier for this interface chain.
+ // We only use this for naming fields; it is never visible to the developer.
+ // This helps with debugging.
+ //
+ // We use i + 1 so that it matches the numbering of our interface offsets. Interface 0
+ // is the "identity" interface.
+
+ let mut ident_string = format!("interface{}", i + 1);
+
+ let suffix = get_interface_ident_suffix(&implement.type_name);
+ if !suffix.is_empty() {
+ ident_string.push('_');
+ ident_string.push_str(&suffix);
+ }
+ let field_ident = syn::Ident::new(&ident_string, implement.span);
+
+ let mut vtable_const_string = ident_string.clone();
+ vtable_const_string.make_ascii_uppercase();
+ vtable_const_string.insert_str(0, "VTABLE_");
+ let vtable_const_ident = syn::Ident::new(&vtable_const_string, implement.span);
+
+ chains.push(InterfaceChain {
+ implement,
+ field_ident,
+ vtable_const_ident,
+ });
+ }
+
+ chains
+}
+
+fn get_interface_ident_suffix(type_name: &str) -> String {
+ let mut suffix = String::new();
+ for c in type_name.chars() {
+ let c = c.to_ascii_lowercase();
+
+ if suffix.len() >= 20 {
+ break;
+ }
+
+ if c.is_ascii_alphanumeric() {
+ suffix.push(c);
+ }
+ }
+
+ suffix
+}
diff --git a/vendor/windows-implement/src/tests.rs b/vendor/windows-implement/src/tests.rs
new file mode 100644
index 00000000..3f5c3493
--- /dev/null
+++ b/vendor/windows-implement/src/tests.rs
@@ -0,0 +1,135 @@
+//! These tests are just a way to quickly run the `#[implement]` macro and see its output.
+//! They don't check the output in any way.
+//!
+//! This exists because of some difficulties of running `cargo expand` against the `#[implement]`
+//! macro. It's also just really convenient. You can see the output by using `--nocapture` and
+//! you'll probably want to restrict the output to a single thread:
+//!
+//! ```text
+//! cargo test -p windows-implement --lib -- --nocapture --test-threads=1
+//! ```
+
+use std::io::{Read, Write};
+use std::process::{Command, Stdio};
+
+use proc_macro2::TokenStream;
+use quote::quote;
+
+fn implement(attributes: TokenStream, item_tokens: TokenStream) -> String {
+ let out_tokens = crate::implement_core(attributes, item_tokens);
+ let tokens_string = out_tokens.to_string();
+
+ let out_string = rustfmt(&tokens_string);
+ println!("// output of #[implement] :");
+ println!();
+ println!("{}", out_string);
+ out_string
+}
+
+fn rustfmt(input: &str) -> String {
+ let mut rustfmt = Command::new("rustfmt");
+
+ rustfmt.stdin(Stdio::piped());
+ rustfmt.stdout(Stdio::piped());
+ rustfmt.stderr(Stdio::inherit());
+
+ let mut child = match rustfmt.spawn() {
+ Ok(c) => c,
+ Err(e) => {
+ eprintln!("failed to spawn rustfmt: {e:?}");
+ return input.to_string();
+ }
+ };
+
+ let mut stdout = child.stdout.take().unwrap();
+
+ // spawn thread to read stdout
+ let stdout_thread = std::thread::spawn(move || {
+ let mut buf = String::new();
+ stdout.read_to_string(&mut buf).unwrap();
+ buf
+ });
+
+ // write unformatted into stdin
+ let mut stdin = child.stdin.take().unwrap();
+ stdin.write_all(input.as_bytes()).unwrap();
+ drop(stdin);
+
+ let stdout_string: String = stdout_thread.join().unwrap();
+
+ let exit = child.wait().unwrap();
+ if !exit.success() {
+ eprintln!("rustfmt terminated with failure status code");
+ return input.to_string();
+ }
+
+ stdout_string
+}
+
+#[test]
+fn simple_type() {
+ implement(
+ quote!(IFoo),
+ quote! {
+ struct Foo {
+ x: u32,
+ }
+ },
+ );
+}
+
+#[test]
+fn zero_sized_type() {
+ implement(
+ quote!(IFoo),
+ quote! {
+ struct Foo;
+ },
+ );
+}
+
+#[test]
+fn no_interfaces() {
+ implement(
+ quote!(),
+ quote! {
+ struct Foo {}
+ },
+ );
+}
+
+#[test]
+fn generic_no_lifetime() {
+ implement(
+ quote!(IAsyncOperationWithProgress<T, P>, IAsyncInfo),
+ quote! {
+ struct OperationWithProgress<T, P>(SyncState<IAsyncOperationWithProgress<T, P>>)
+ where
+ T: RuntimeType + 'static,
+ P: RuntimeType + 'static;
+
+ },
+ );
+}
+
+#[test]
+fn generic_with_lifetime() {
+ implement(
+ quote!(),
+ quote! {
+ pub struct Foo<'a> {
+ pub x: &'a [u8],
+ }
+ },
+ );
+}
+
+#[test]
+fn tuple_type() {
+ implement(
+ quote!(IFoo),
+ quote! {
+ struct Foo(pub i32);
+ },
+ );
+}