diff options
Diffstat (limited to 'vendor/windows-bindgen')
46 files changed, 6785 insertions, 0 deletions
diff --git a/vendor/windows-bindgen/.cargo-checksum.json b/vendor/windows-bindgen/.cargo-checksum.json new file mode 100644 index 000000000..1515d8f7b --- /dev/null +++ b/vendor/windows-bindgen/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"d3fb5d2a2914f8722455a23bc7480ece5294fac9f6569bc10d2cd2f4e7199d9b","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"d7baa101eb75cfcd7780483b912e89cac34b3a09bac6bd211b65227862195e66","rustfmt.toml":"8f201bf4d9ff69411e98031ad1b168f58ce02d91fd33bc80406115c2506355d4","src/classes.rs":"544c1a44311c4ea01746bdd6728dbd86b1052aa49369230394eb61b69a199c81","src/com_methods.rs":"62e40fa4fe127c8f51b955132030bb0c2eb154f0e0477bdee00cac96e1a5e81e","src/constants.rs":"baefaface9c8a62a2c511c6d23298d18995c5f66b6b9d33d8e02ec9304d74a63","src/delegates.rs":"48e5130d112cc44678af6546a3f1a4c280dea4ac669d4bfc34200201663d08a9","src/enums.rs":"c9139821ae052d522dd54d3f246eb4f59b264d1e155b1addec1128abd78840c4","src/extensions/impl/Foundation/Collections/Iterable.rs":"873c3d33ee6446beda43126ca2a0f58405078b48fd1b3beb18bb43ef7fd4d9d1","src/extensions/impl/Foundation/Collections/MapView.rs":"262ec7c72ec75cdea4f905efec24a4a9c58411d1804673e4e6219509a0ca27df","src/extensions/impl/Foundation/Collections/VectorView.rs":"ea4a71a8fd7e3b4400d1d63ee0f2a3ca0a7521377285c6921430554529c920fe","src/extensions/mod.rs":"d50589d2c41328809650538a2bcba45557aba0247e70033c91845de153ab8766","src/extensions/mod/Foundation/IInspectable.rs":"28053647ee2c91287321b165949411aa659d2f5a396184759f066c707750f538","src/extensions/mod/Foundation/Numerics/Matrix3x2.rs":"43c2bd8389b7de6bff266e91fafd03c27da56632d47a0d47ed17cf429b8538cc","src/extensions/mod/Foundation/Numerics/Matrix4x4.rs":"da469abb2a40632935f37074b1e9c726d8742fbb3d1c2804674fd287ad3c2979","src/extensions/mod/Foundation/Numerics/Vector2.rs":"d20b8b59fa2193cb81c8d9ccd7e15c5f7827e7392a35bb9d10af42ab4ccd75ac","src/extensions/mod/Foundation/Numerics/Vector3.rs":"df851b7f059e3f31bf0eb76f0515312a68465b2489a8b68f03bdcddf4b47e693","src/extensions/mod/Foundation/Numerics/Vector4.rs":"f309f3e1e0c34b9db3137f113a3519ac1708aaa1aacb899b4b59f0228497e1a4","src/extensions/mod/Foundation/PropertyValue.rs":"c451b9388b3a9023f991e91a0ba48a403b7507fda529532a0042c910b4b04055","src/extensions/mod/Foundation/TimeSpan.rs":"b6de4e26e155771d8ad9e3117e8b33d18f7a4dfc1c2b46ae59b0bad52710ce11","src/extensions/mod/Win32/Foundation/BOOL.rs":"44171d9050b2c8ac3b34677073573f209aafd29e8c6a06bffe9b4619f1317e9b","src/extensions/mod/Win32/Foundation/BOOLEAN.rs":"b203f08c6e7bffbf3b9d41f48f7bd6422c5c38ea7284bd66f1e25377e1e721fe","src/extensions/mod/Win32/Foundation/NTSTATUS.rs":"aba61020a2736b57164290b2a9d605f38185a7a7e02d39449437746064b22513","src/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs":"f517c0d3cc8b3cbd218d84c32ad81f8d6b4f1c3b59f688de7a63afda59d46ce8","src/extensions/mod/Win32/Foundation/WIN32_ERROR.rs":"71b8aed03fdc69a6efb8ed5ec584863a6113ceb1e2968d0b4f605701029ac7c5","src/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs":"77bfd4761e35c07092389e746553352fae9c265c8362402389c75cfbe0051b4b","src/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs":"a69b030fb1082d7f6d610ac95c60ec86b6f67cc10181cb2152408003cf1dc95c","src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs":"126e342356b0e1244d4c9489c421281215ff7a857b1b234a50c042ac27caf1a7","src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs":"3479563d2ba7cbb94987605a736b1a62f7a0286dc141a11b48969910a9082462","src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs":"ebda0e371f36f0fa782ec0c37ad47c19540a20a58e7810570968357f6f54fef9","src/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs":"fe5e01b7126c9fe7e7d4ee82a4b3f266b0306e1de20a33476b1ba8f3a782533c","src/functions.rs":"3cfeac90f2f1d0e9df85710e3fa4d90a3107d6454b6f911dff45d81894aa436d","src/gen.rs":"7ef87eaa513662aa8e6e0825ec946b2f03820edcdb22263672974218d2f159b5","src/handles.rs":"054c4491d2c3e58c4987ab00e81003119b4978b81f548fe77c31e7a0063eb015","src/implements.rs":"4098f447a4a830fe1644196fc60b22ff23c12f6269950278651cad98bc5ab509","src/interfaces.rs":"b4c57ae2f7c871c47f4f3728e0fc5fef2e4e5e637c52a2d1a8eb8533b8e27909","src/iterators.rs":"c057d9f021a30e5bcb8daa0a7282e453174c7c6b5e04fafc444e59fbc30d7b22","src/lib.rs":"dd48701aab64a6823703458b134458f93fa349f8919b11d8c54c607177821d9e","src/method_names.rs":"d367fd2c75abc7977b1b17e49e4867e1a602bd56bb8a4188de8fbaa203305917","src/standalone.rs":"6aca1fa4bd47d61343b3873153115d64eb82c5471a280833c0f875c62d8aa051","src/structs.rs":"922e1745fa2919145dd92e7fd15f9237d8584180144ac8138ab17ebdaeeafc09","src/try_format.rs":"ffe15866050fdc9424749c572001953064347d499a06b15d6df783b38011289d","src/winrt_methods.rs":"3cee31e1628a246d67d8265a967ff2c42ff3c436218993817b7c6a331afc9e7f"},"package":"b6935fb09b84ee57929ae92518b475f5dfdfbeb87c5334756acc28ee8e202b60"}
\ No newline at end of file diff --git a/vendor/windows-bindgen/Cargo.toml b/vendor/windows-bindgen/Cargo.toml new file mode 100644 index 000000000..285ac36ad --- /dev/null +++ b/vendor/windows-bindgen/Cargo.toml @@ -0,0 +1,32 @@ +# 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 = "2018" +name = "windows-bindgen" +version = "0.49.0" +authors = ["Microsoft"] +description = "Code gen support for the windows and windows-sys crates" +readme = "readme.md" +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 = [] + +[dependencies.metadata] +version = "0.49.0" +package = "windows-metadata" + +[dependencies.tokens] +version = "0.48.0" +package = "windows-tokens" diff --git a/vendor/windows-bindgen/license-apache-2.0 b/vendor/windows-bindgen/license-apache-2.0 new file mode 100644 index 000000000..b5ed4ecec --- /dev/null +++ b/vendor/windows-bindgen/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-bindgen/license-mit b/vendor/windows-bindgen/license-mit new file mode 100644 index 000000000..9e841e7a2 --- /dev/null +++ b/vendor/windows-bindgen/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-bindgen/readme.md b/vendor/windows-bindgen/readme.md new file mode 100644 index 000000000..3a54efce8 --- /dev/null +++ b/vendor/windows-bindgen/readme.md @@ -0,0 +1,88 @@ +## Rust for Windows + +The [windows](https://crates.io/crates/windows) and [windows-sys](https://crates.io/crates/windows-sys) crates let you call any Windows API past, present, and future using code generated on the fly directly from the [metadata describing the API](https://github.com/microsoft/windows-rs/tree/master/crates/libs/metadata/default) and right into your Rust package where you can call them as if they were just another Rust module. The Rust language projection follows in the tradition established by [C++/WinRT](https://github.com/microsoft/cppwinrt) of building language projections for Windows using standard languages and compilers, providing a natural and idiomatic way for Rust developers to call Windows APIs. + +* [Getting started](https://kennykerr.ca/rust-getting-started/) +* [Samples](https://github.com/microsoft/windows-rs/tree/0.48.0/crates/samples) +* [Releases](https://github.com/microsoft/windows-rs/releases) + +Start by adding the following to your Cargo.toml file: + +```toml +[dependencies.windows] +version = "0.48" +features = [ + "Data_Xml_Dom", + "Win32_Foundation", + "Win32_Security", + "Win32_System_Threading", + "Win32_UI_WindowsAndMessaging", +] +``` + +Make use of any Windows APIs as needed: + +```rust,no_run +use windows::{ + core::*, Data::Xml::Dom::*, Win32::Foundation::*, Win32::System::Threading::*, + Win32::UI::WindowsAndMessaging::*, +}; + +fn main() -> Result<()> { + let doc = XmlDocument::new()?; + doc.LoadXml(h!("<html>hello world</html>"))?; + + let root = doc.DocumentElement()?; + assert!(root.NodeName()? == "html"); + assert!(root.InnerText()? == "hello world"); + + unsafe { + let event = CreateEventW(None, true, false, None)?; + SetEvent(event).ok()?; + WaitForSingleObject(event, 0); + CloseHandle(event).ok()?; + + MessageBoxA(None, s!("Ansi"), s!("Caption"), MB_OK); + MessageBoxW(None, w!("Wide"), w!("Caption"), MB_OK); + } + + Ok(()) +} +``` + +## windows-sys + +The `windows-sys` crate is a zero-overhead fallback for the most demanding situations and primarily where the absolute best compile time is essential. It only includes function declarations (externs), structs, and constants. No convenience helpers, traits, or wrappers are provided. + +Start by adding the following to your Cargo.toml file: + +```toml +[dependencies.windows-sys] +version = "0.48" +features = [ + "Win32_Foundation", + "Win32_Security", + "Win32_System_Threading", + "Win32_UI_WindowsAndMessaging", +] +``` + +Make use of any Windows APIs as needed: + +```rust,no_run +use windows_sys::{ + core::*, Win32::Foundation::*, Win32::System::Threading::*, Win32::UI::WindowsAndMessaging::*, +}; + +fn main() { + unsafe { + let event = CreateEventW(std::ptr::null(), 1, 0, std::ptr::null()); + SetEvent(event); + WaitForSingleObject(event, 0); + CloseHandle(event); + + MessageBoxA(0, s!("Ansi"), s!("Caption"), MB_OK); + MessageBoxW(0, w!("Wide"), w!("Caption"), MB_OK); + } +} +``` diff --git a/vendor/windows-bindgen/rustfmt.toml b/vendor/windows-bindgen/rustfmt.toml new file mode 100644 index 000000000..43d4840c7 --- /dev/null +++ b/vendor/windows-bindgen/rustfmt.toml @@ -0,0 +1 @@ +newline_style = "Unix" diff --git a/vendor/windows-bindgen/src/classes.rs b/vendor/windows-bindgen/src/classes.rs new file mode 100644 index 000000000..3cdf50006 --- /dev/null +++ b/vendor/windows-bindgen/src/classes.rs @@ -0,0 +1,215 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.sys { + if gen.reader.type_def_has_default_interface(def) { + let name = to_ident(gen.reader.type_def_name(def)); + quote! { + pub type #name = *mut ::core::ffi::c_void; + } + } else { + quote! {} + } + } else { + gen_class(gen, def) + } +} + +fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.reader.type_def_extends(def) == TypeName::Attribute { + return TokenStream::new(); + } + + let name = to_ident(gen.reader.type_def_name(def)); + let interfaces = gen + .reader + .type_interfaces(&Type::TypeDef((def, Vec::new()))); + let mut methods = quote! {}; + let mut method_names = MethodNames::new(); + + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + for interface in &interfaces { + if let Type::TypeDef((def, generics)) = &interface.ty { + let mut virtual_names = MethodNames::new(); + + for method in gen.reader.type_def_methods(*def) { + methods.combine(&winrt_methods::gen( + gen, + *def, + generics, + interface.kind, + method, + &mut method_names, + &mut virtual_names, + )); + } + } + } + + let factories = interfaces.iter().filter_map(|interface| match interface.kind { + InterfaceKind::Static => { + if let Type::TypeDef((def, generics)) = &interface.ty { + if gen.reader.type_def_methods(*def).next().is_some() { + let interface_type = gen.type_name(&interface.ty); + let features = gen.cfg_features(&gen.reader.type_def_cfg(*def, generics)); + + let hidden = if gen.doc { + quote! { #[doc(hidden)] } + } else { + quote! {} + }; + + return Some(quote! { + #hidden + #features + pub fn #interface_type<R, F: FnOnce(&#interface_type) -> ::windows::core::Result<R>>( + callback: F, + ) -> ::windows::core::Result<R> { + static SHARED: ::windows::imp::FactoryCache<#name, #interface_type> = + ::windows::imp::FactoryCache::new(); + SHARED.call(callback) + } + }); + } + } + None + } + _ => None, + }); + + if gen.reader.type_def_has_default_interface(def) { + let new = if gen.reader.type_def_has_default_constructor(def) { + quote! { + pub fn new() -> ::windows::core::Result<Self> { + Self::IActivationFactory(|f| f.ActivateInstance::<Self>()) + } + fn IActivationFactory<R, F: FnOnce(&::windows::imp::IGenericFactory) -> ::windows::core::Result<R>>( + callback: F, + ) -> ::windows::core::Result<R> { + static SHARED: ::windows::imp::FactoryCache<#name, ::windows::imp::IGenericFactory> = + ::windows::imp::FactoryCache::new(); + SHARED.call(callback) + } + } + } else { + quote! {} + }; + + let mut tokens = quote! { + #doc + #features + #[repr(transparent)] + pub struct #name(::windows::core::IUnknown); + #features + impl #name { + #new + #methods + #(#factories)* + } + }; + + tokens.combine(&gen.interface_core_traits( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&gen.interface_winrt_trait( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&gen.interface_trait(def, &[], &name, &TokenStream::new(), &features, true)); + tokens.combine(&gen.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); + tokens.combine(&gen.async_get( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&iterators::gen( + gen, + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &cfg, + )); + tokens.combine(&gen_conversions(gen, def, &name, &interfaces, &cfg)); + tokens.combine(&gen.agile(def, &name, &TokenStream::new(), &features)); + tokens + } else { + let mut tokens = quote! { + #doc + #features + pub struct #name; + #features + impl #name { + #methods + #(#factories)* + } + }; + + tokens.combine(&gen.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); + tokens + } +} + +fn gen_conversions( + gen: &Gen, + def: TypeDef, + name: &TokenStream, + interfaces: &[Interface], + cfg: &Cfg, +) -> TokenStream { + let features = gen.cfg_features(cfg); + let mut tokens = quote! { + #features + ::windows::imp::interface_hierarchy!(#name, ::windows::core::IUnknown, ::windows::core::IInspectable); + }; + + for interface in interfaces { + if gen.reader.type_is_exclusive(&interface.ty) { + continue; + } + + if interface.kind != InterfaceKind::Default + && interface.kind != InterfaceKind::None + && interface.kind != InterfaceKind::Base + { + continue; + } + + let into = gen.type_name(&interface.ty); + // TODO: simplify - maybe provide + operator? + let features = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(&interface.ty))); + + tokens.combine("e! { + #features + impl ::windows::core::CanTryInto<#into> for #name {} + }); + } + + for def in gen.reader.type_def_bases(def) { + let into = gen.type_def_name(def, &[]); + let features = gen.cfg_features(&cfg.union(&gen.reader.type_def_cfg(def, &[]))); + + tokens.combine("e! { + #features + impl ::windows::core::CanTryInto<#into> for #name {} + }); + } + + tokens +} diff --git a/vendor/windows-bindgen/src/com_methods.rs b/vendor/windows-bindgen/src/com_methods.rs new file mode 100644 index 000000000..cb59b9d64 --- /dev/null +++ b/vendor/windows-bindgen/src/com_methods.rs @@ -0,0 +1,238 @@ +use super::*; + +pub fn gen( + gen: &Gen, + def: TypeDef, + kind: InterfaceKind, + method: MethodDef, + method_names: &mut MethodNames, + virtual_names: &mut MethodNames, + base_count: usize, +) -> TokenStream { + let signature = gen.reader.method_def_signature(method, &[]); + let name = method_names.add(gen, method); + let vname = virtual_names.add(gen, method); + let generics = gen.constraint_generics(&signature.params); + let where_clause = gen.where_clause(&signature.params); + let mut cfg = gen.reader.signature_cfg(&signature); + cfg.add_feature(gen.reader.type_def_namespace(def)); + let doc = gen.cfg_method_doc(&cfg); + let features = gen.cfg_features(&cfg); + + if kind == InterfaceKind::None { + return quote! {}; + } + + let mut bases = quote! {}; + + for _ in 0..base_count { + bases.combine("e! { .base__ }); + } + + let kind = gen.reader.signature_kind(&signature); + match kind { + SignatureKind::Query(_) => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let generics = expand_generics(generics, quote!(T)); + let where_clause = + expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface)); + + quote! { + #doc + #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__) + } + } + } + SignatureKind::QueryOptional(_) => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let generics = expand_generics(generics, quote!(T)); + let where_clause = + expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface)); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params result__: *mut ::core::option::Option<T>) -> ::windows::core::Result<()> #where_clause { + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args).ok() + } + } + } + SignatureKind::ResultValue => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let return_type = gen.type_name(&return_type); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> ::windows::core::Result<#return_type> #where_clause { + let mut result__ = ::windows::core::zeroed::<#return_type>(); + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args).from_abi(result__) + } + } + } + SignatureKind::ResultVoid => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> ::windows::core::Result<()> #where_clause { + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args).ok() + } + } + } + SignatureKind::ReturnValue => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let is_nullable = gen.reader.type_is_nullable(&return_type); + let return_type = gen.type_name(&return_type); + + if is_nullable { + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> ::windows::core::Result<#return_type> #where_clause { + let mut result__ = ::windows::core::zeroed::<#return_type>(); + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args); + ::windows::core::from_abi(result__) + } + } + } else { + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> #return_type #where_clause { + let mut result__ = ::windows::core::zeroed::<#return_type>(); + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args); + ::std::mem::transmute(result__) + } + } + } + } + SignatureKind::ReturnStruct => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = gen.type_name(&signature.return_type.unwrap()); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> #return_type #where_clause { + let mut result__: #return_type = ::core::mem::zeroed(); + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), &mut result__, #args); + result__ + } + } + } + SignatureKind::PreserveSig => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = gen.return_sig(&signature); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) #return_type #where_clause { + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args) + } + } + } + SignatureKind::ReturnVoid => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) #where_clause { + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args) + } + } + } + } +} + +pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream { + match gen.reader.signature_kind(sig) { + SignatureKind::ResultValue => { + let invoke_args = sig.params[..sig.params.len() - 1] + .iter() + .map(|param| gen_win32_invoke_arg(gen, param)); + + let result = gen.param_name(sig.params[sig.params.len() - 1].def); + + quote! { + match #inner(#(#invoke_args,)*) { + ::core::result::Result::Ok(ok__) => { + // use `core::ptr::write` since the result could be uninitialized + ::core::ptr::write(#result, ::core::mem::transmute(ok__)); + ::windows::core::HRESULT(0) + } + ::core::result::Result::Err(err) => err.into() + } + } + } + SignatureKind::Query(_) | SignatureKind::QueryOptional(_) | SignatureKind::ResultVoid => { + let invoke_args = sig + .params + .iter() + .map(|param| gen_win32_invoke_arg(gen, param)); + + quote! { + #inner(#(#invoke_args,)*).into() + } + } + SignatureKind::ReturnStruct => { + let invoke_args = sig + .params + .iter() + .map(|param| gen_win32_invoke_arg(gen, param)); + + quote! { + *result__ = #inner(#(#invoke_args,)*) + } + } + _ => { + let invoke_args = sig + .params + .iter() + .map(|param| gen_win32_invoke_arg(gen, param)); + + quote! { + #inner(#(#invoke_args,)*) + } + } + } +} + +fn gen_win32_invoke_arg(gen: &Gen, param: &SignatureParam) -> TokenStream { + let name = gen.param_name(param.def); + + if gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + && gen.reader.type_is_nullable(¶m.ty) + { + quote! { ::windows::core::from_raw_borrowed(&#name) } + } else if (!param.ty.is_pointer() && gen.reader.type_is_nullable(¶m.ty)) + || (gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + && !gen.reader.type_is_primitive(¶m.ty)) + { + quote! { ::core::mem::transmute(&#name) } + } else { + quote! { ::core::mem::transmute_copy(&#name) } + } +} diff --git a/vendor/windows-bindgen/src/constants.rs b/vendor/windows-bindgen/src/constants.rs new file mode 100644 index 000000000..1a08db0ae --- /dev/null +++ b/vendor/windows-bindgen/src/constants.rs @@ -0,0 +1,188 @@ +use super::*; + +pub fn gen(gen: &Gen, def: Field) -> TokenStream { + let name = to_ident(gen.reader.field_name(def)); + let ty = gen.reader.field_type(def, None).to_const_type(); + let cfg = gen.reader.field_cfg(def); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + if let Some(constant) = gen.reader.field_constant(def) { + let constant_type = gen.reader.constant_type(constant); + + if ty == constant_type { + if ty == Type::String { + let crate_name = gen.crate_name(); + if gen.reader.field_is_ansi(def) { + let value = gen.value(&gen.reader.constant_value(constant)); + quote! { + #doc + #features + pub const #name: #crate_name PCSTR = #crate_name s!(#value); + } + } else { + let value = gen.value(&gen.reader.constant_value(constant)); + quote! { + #doc + #features + pub const #name: #crate_name PCWSTR = #crate_name w!(#value); + } + } + } else { + let value = gen.typed_value(&gen.reader.constant_value(constant)); + quote! { + #doc + #features + pub const #name: #value; + } + } + } else { + let kind = gen.type_default_name(&ty); + let value = gen.value(&gen.reader.constant_value(constant)); + let underlying_type = gen.reader.type_underlying_type(&ty); + + let value = if underlying_type == constant_type { + value + } else if gen.std && underlying_type == Type::ISize { + quote! { ::core::ptr::invalid_mut(#value as _) } + } else { + quote! { #value as _ } + }; + + if !gen.sys && gen.reader.type_has_replacement(&ty) { + quote! { + #doc + #features + pub const #name: #kind = #kind(#value); + } + } else { + quote! { + #doc + #features + pub const #name: #kind = #value; + } + } + } + } else if let Some(guid) = gen.reader.field_guid(def) { + let value = gen.guid(&guid); + let guid = gen.type_name(&Type::GUID); + quote! { + #doc + pub const #name: #guid = #value; + } + } else if let Some(value) = initializer(gen, def) { + let kind = gen.type_default_name(&ty); + + quote! { + #doc + #features + pub const #name: #kind = #kind { #value }; + } + } else { + quote! {} + } +} + +fn initializer(gen: &Gen, def: Field) -> Option<TokenStream> { + let Some(value) = constant(gen, def) else { + return None; + }; + + let mut input = value.as_str(); + + let Type::TypeDef((def, _)) = gen.reader.field_type(def, None) else { + unimplemented!(); + }; + + let mut result = quote! {}; + + for field in gen.reader.type_def_fields(def) { + let (value, rest) = field_initializer(gen, field, input); + input = rest; + result.combine(&value); + } + + Some(result) +} + +fn field_initializer<'a>(gen: &Gen, field: Field, input: &'a str) -> (TokenStream, &'a str) { + let name = to_ident(gen.reader.field_name(field)); + + match gen.reader.field_type(field, None) { + Type::GUID => { + let (literals, rest) = read_literal_array(input, 11); + let value = gen.guid(&GUID::from_string_args(&literals)); + (quote! { #name: #value, }, rest) + } + Type::Win32Array((_, len)) => { + let (literals, rest) = read_literal_array(input, len); + let literals = literals.iter().map(|literal| TokenStream::from(*literal)); + (quote! { #name: [#(#literals,)*], }, rest) + } + _ => { + let (literal, rest) = read_literal(input); + let literal: TokenStream = literal.into(); + (quote! { #name: #literal, }, rest) + } + } +} + +fn constant(gen: &Gen, def: Field) -> Option<String> { + gen.reader + .field_attributes(def) + .find(|attribute| gen.reader.attribute_name(*attribute) == "ConstantAttribute") + .map(|attribute| { + let args = gen.reader.attribute_args(attribute); + match &args[0].1 { + Value::String(value) => value.clone(), + _ => unimplemented!(), + } + }) +} + +fn read_literal(input: &str) -> (&str, &str) { + let mut start = None; + let mut end = 0; + + for (pos, c) in input.bytes().enumerate() { + if start.is_none() { + if c != b' ' && c != b',' { + start = Some(pos); + } + } else if c == b' ' || c == b',' || c == b'}' { + break; + } + end += 1; + } + + let Some(start) = start else { + unimplemented!(); + }; + + (&input[start..end], &input[end..]) +} + +fn read_token(input: &str, token: u8) -> &str { + for (pos, c) in input.bytes().enumerate() { + if c == token { + return &input[pos + 1..]; + } else if c != b' ' && c != b',' { + break; + } + } + + panic!("`{}` expected", token.escape_ascii()); +} + +fn read_literal_array(input: &str, len: usize) -> (Vec<&str>, &str) { + let mut input = read_token(input, b'{'); + let mut result = vec![]; + + for _ in 0..len { + let (literal, rest) = read_literal(input); + result.push(literal); + input = rest; + } + + (result, read_token(input, b'}')) +} diff --git a/vendor/windows-bindgen/src/delegates.rs b/vendor/windows-bindgen/src/delegates.rs new file mode 100644 index 000000000..a68719c81 --- /dev/null +++ b/vendor/windows-bindgen/src/delegates.rs @@ -0,0 +1,181 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + gen_delegate(gen, def) + } else { + gen_callback(gen, def) + } +} + +fn gen_callback(gen: &Gen, def: TypeDef) -> TokenStream { + let name = to_ident(gen.reader.type_def_name(def)); + + let method = gen.reader.type_def_invoke_method(def); + let signature = gen.reader.method_def_signature(method, &[]); + let return_type = gen.return_sig(&signature); + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + let params = signature.params.iter().map(|p| { + let name = gen.param_name(p.def); + let tokens = gen.type_default_name(&p.ty); + quote! { #name: #tokens } + }); + + quote! { + #doc + #features + pub type #name = ::core::option::Option<unsafe extern "system" fn(#(#params),*) #return_type>; + } +} + +fn gen_delegate(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.sys { + let name = to_ident(gen.reader.type_def_name(def)); + quote! { + pub type #name = *mut ::core::ffi::c_void; + } + } else { + gen_win_delegate(gen, def) + } +} + +fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream { + let name = to_ident(gen.reader.type_def_name(def)); + let vtbl = name.join("_Vtbl"); + let boxed = name.join("Box"); + + let generics: &Vec<Type> = &gen.reader.type_def_generics(def).collect(); + let phantoms = gen.generic_phantoms(generics); + let named_phantoms = gen.generic_named_phantoms(generics); + let constraints = gen.generic_constraints(generics); + let generic_names = gen.generic_names(generics); + + let ident = gen.type_def_name(def, generics); + + let method = gen.reader.type_def_invoke_method(def); + let signature = gen.reader.method_def_signature(method, generics); + let fn_constraint = gen_fn_constraint(gen, def, &signature); + + let cfg = gen.reader.type_def_cfg(def, generics); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + let vtbl_signature = gen.vtbl_signature(def, generics, &signature); + let invoke = winrt_methods::gen( + gen, + def, + generics, + InterfaceKind::Default, + method, + &mut MethodNames::new(), + &mut MethodNames::new(), + ); + let invoke_upcall = winrt_methods::gen_upcall(gen, &signature, quote! { ((*this).invoke) }); + + let mut tokens = quote! { + #doc + #features + #[repr(transparent)] + pub struct #ident(pub ::windows::core::IUnknown, #phantoms) where #constraints; + #features + impl<#constraints> #ident { + pub fn new<#fn_constraint>(invoke: F) -> Self { + let com = #boxed::<#generic_names F> { + vtable: &#boxed::<#generic_names F>::VTABLE, + count: ::windows::imp::RefCount::new(1), + invoke, + }; + unsafe { + ::core::mem::transmute(::std::boxed::Box::new(com)) + } + } + #invoke + } + #features + #[repr(C)] + struct #boxed<#generic_names #fn_constraint> where #constraints { + vtable: *const #vtbl<#generic_names>, + invoke: F, + count: ::windows::imp::RefCount, + } + #features + impl<#constraints #fn_constraint> #boxed<#generic_names F> { + const VTABLE: #vtbl<#generic_names> = #vtbl::<#generic_names>{ + base__: ::windows::core::IUnknown_Vtbl{QueryInterface: Self::QueryInterface, AddRef: Self::AddRef, Release: Self::Release}, + Invoke: Self::Invoke, + #(#named_phantoms)* + }; + unsafe extern "system" fn QueryInterface(this: *mut ::core::ffi::c_void, iid: &::windows::core::GUID, interface: *mut *const ::core::ffi::c_void) -> ::windows::core::HRESULT { + let this = this as *mut *mut ::core::ffi::c_void as *mut Self; + + *interface = if iid == &<#ident as ::windows::core::ComInterface>::IID || + iid == &<::windows::core::IUnknown as ::windows::core::ComInterface>::IID || + iid == &<::windows::imp::IAgileObject as ::windows::core::ComInterface>::IID { + &mut (*this).vtable as *mut _ as _ + } else { + ::core::ptr::null_mut() + }; + + // TODO: implement IMarshal + + if (*interface).is_null() { + ::windows::core::HRESULT(-2147467262) // E_NOINTERFACE + } else { + (*this).count.add_ref(); + ::windows::core::HRESULT(0) + } + } + unsafe extern "system" fn AddRef(this: *mut ::core::ffi::c_void) -> u32 { + let this = this as *mut *mut ::core::ffi::c_void as *mut Self; + (*this).count.add_ref() + } + unsafe extern "system" fn Release(this: *mut ::core::ffi::c_void) -> u32 { + let this = this as *mut *mut ::core::ffi::c_void as *mut Self; + let remaining = (*this).count.release(); + + if remaining == 0 { + let _ = ::std::boxed::Box::from_raw(this); + } + + remaining + } + unsafe extern "system" fn Invoke #vtbl_signature { + let this = this as *mut *mut ::core::ffi::c_void as *mut Self; + #invoke_upcall + } + } + }; + + tokens.combine(&gen.interface_core_traits( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&gen.interface_trait(def, generics, &ident, &constraints, &features, true)); + tokens.combine(&gen.interface_winrt_trait( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&gen.interface_vtbl(def, generics, &ident, &constraints, &features)); + tokens +} + +fn gen_fn_constraint(gen: &Gen, def: TypeDef, signature: &Signature) -> TokenStream { + let signature = gen.impl_signature(def, signature); + + quote! { F: FnMut #signature + ::core::marker::Send + 'static } +} diff --git a/vendor/windows-bindgen/src/enums.rs b/vendor/windows-bindgen/src/enums.rs new file mode 100644 index 000000000..ee7616fda --- /dev/null +++ b/vendor/windows-bindgen/src/enums.rs @@ -0,0 +1,203 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + let type_name = gen.reader.type_def_type_name(def); + let ident = to_ident(type_name.name); + let underlying_type = gen.reader.type_def_underlying_type(def); + let underlying_type = gen.type_name(&underlying_type); + let is_scoped = gen.reader.type_def_is_scoped(def); + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + let fields: Vec<(TokenStream, TokenStream)> = gen + .reader + .type_def_fields(def) + .filter_map(|field| { + if gen + .reader + .field_flags(field) + .contains(FieldAttributes::LITERAL) + { + let field_name = to_ident(gen.reader.field_name(field)); + let constant = gen.reader.field_constant(field).unwrap(); + let value = gen.value(&gen.reader.constant_value(constant)); + + Some((field_name, value)) + } else { + None + } + }) + .collect(); + + let eq = if gen.sys { + quote! {} + } else { + quote! { + // Unfortunately, Rust requires these to be derived to allow constant patterns. + #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] + } + }; + + let mut tokens = if is_scoped || !gen.sys { + quote! { + #doc + #features + #[repr(transparent)] + #eq + pub struct #ident(pub #underlying_type); + } + } else { + quote! { + #doc + #features + pub type #ident = #underlying_type; + } + }; + + tokens.combine(&if is_scoped { + let fields = fields.iter().map(|(field_name, value)| { + quote! { + pub const #field_name: Self = Self(#value); + } + }); + + quote! { + #features + impl #ident { + #(#fields)* + } + } + } else if !gen.sys { + let fields = fields.iter().map(|(field_name, value)| { + quote! { + #doc + #features + pub const #field_name: #ident = #ident(#value); + } + }); + + quote! { + #(#fields)* + } + } else if !gen.standalone { + let fields = fields.iter().map(|(field_name, value)| { + quote! { + #doc + #features + pub const #field_name: #ident = #value; + } + }); + + quote! { + #(#fields)* + } + } else { + quote! {} + }); + + if is_scoped || !gen.sys { + tokens.combine("e! { + #features + impl ::core::marker::Copy for #ident {} + #features + impl ::core::clone::Clone for #ident { + fn clone(&self) -> Self { + *self + } + } + }); + } + + if !gen.sys { + tokens.combine("e! { + #features + impl ::core::default::Default for #ident { + fn default() -> Self { + Self(0) + } + } + }); + } + + if !gen.sys { + let name = type_name.name; + tokens.combine("e! { + #features + impl ::windows::core::TypeKind for #ident { + type TypeKind = ::windows::core::CopyType; + } + #features + impl ::core::fmt::Debug for #ident { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple(#name).field(&self.0).finish() + } + } + }); + + if gen.reader.type_def_is_flags(def) { + tokens.combine("e! { + #features + impl #ident { + pub const fn contains(&self, other: Self) -> bool { + self.0 & other.0 == other.0 + } + } + #features + impl ::core::ops::BitOr for #ident { + type Output = Self; + + fn bitor(self, other: Self) -> Self { + Self(self.0 | other.0) + } + } + #features + impl ::core::ops::BitAnd for #ident { + type Output = Self; + + fn bitand(self, other: Self) -> Self { + Self(self.0 & other.0) + } + } + #features + impl ::core::ops::BitOrAssign for #ident { + fn bitor_assign(&mut self, other: Self) { + self.0.bitor_assign(other.0) + } + } + #features + impl ::core::ops::BitAndAssign for #ident { + fn bitand_assign(&mut self, other: Self) { + self.0.bitand_assign(other.0) + } + } + #features + impl ::core::ops::Not for #ident { + type Output = Self; + + fn not(self) -> Self { + Self(self.0.not()) + } + } + }); + } + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + let signature = + Literal::byte_string(gen.reader.type_def_signature(def, &[]).as_bytes()); + + tokens.combine("e! { + #features + impl ::windows::core::RuntimeType for #ident { + const SIGNATURE: ::windows::imp::ConstBuffer = ::windows::imp::ConstBuffer::from_slice(#signature); + } + }); + } + } + + tokens +} diff --git a/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/Iterable.rs b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/Iterable.rs new file mode 100644 index 000000000..7d379fdf6 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/Iterable.rs @@ -0,0 +1,96 @@ +#[::windows::core::implement(IIterable<T>)] +struct StockIterable<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 StockIterable<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(StockIterator { + owner: self.cast()?, + current: 0.into(), + } + .into()) + } + } +} + +#[::windows::core::implement(IIterator<T>)] +struct StockIterator<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 StockIterator<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: &StockIterable<T> = ::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: &StockIterable<T> = ::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: &StockIterable<T> = ::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: &StockIterable<T> = ::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(StockIterable { values }.into()) + } +} diff --git a/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/MapView.rs b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/MapView.rs new file mode 100644 index 000000000..e8980e4d2 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/MapView.rs @@ -0,0 +1,174 @@ +#[windows::core::implement(IMapView<K, V>, IIterable<IKeyValuePair<K, V>>)] +struct StockMapView<K, V> +where + K: windows::core::RuntimeType + 'static, + V: windows::core::RuntimeType + 'static, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + map: std::collections::BTreeMap<K::Default, V::Default>, +} + +impl<K, V> IIterable_Impl<IKeyValuePair<K, V>> for StockMapView<K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + fn First(&self) -> windows::core::Result<IIterator<IKeyValuePair<K, V>>> { + 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(StockMapViewIterator::<K, V> { + _owner: self.cast()?, + current: std::sync::RwLock::new(self.map.iter()), + } + .into()) + } + } +} + +impl<K, V> IMapView_Impl<K, V> for StockMapView<K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + fn Lookup(&self, key: &K::Default) -> windows::core::Result<V> { + let value = self + .map + .get(key) + .ok_or_else(|| windows::core::Error::from(windows::imp::E_BOUNDS))?; + V::from_default(value) + } + fn Size(&self) -> windows::core::Result<u32> { + Ok(self.map.len() as _) + } + fn HasKey(&self, key: &K::Default) -> windows::core::Result<bool> { + Ok(self.map.contains_key(key)) + } + fn Split( + &self, + first: &mut std::option::Option<IMapView<K, V>>, + second: &mut std::option::Option<IMapView<K, V>>, + ) -> windows::core::Result<()> { + *first = None; + *second = None; + Ok(()) + } +} + +#[::windows::core::implement(IIterator<IKeyValuePair<K, V>>)] +struct StockMapViewIterator<'a, K, V> +where + K: windows::core::RuntimeType + 'static, + V: windows::core::RuntimeType + 'static, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + _owner: IIterable<IKeyValuePair<K, V>>, + current: ::std::sync::RwLock<std::collections::btree_map::Iter<'a, K::Default, V::Default>>, +} + +impl<'a, K, V> IIterator_Impl<IKeyValuePair<K, V>> for StockMapViewIterator<'a, K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + fn Current(&self) -> ::windows::core::Result<IKeyValuePair<K, V>> { + let mut current = self.current.read().unwrap().clone().peekable(); + + if let Some((key, value)) = current.peek() { + Ok(StockKeyValuePair { + key: (*key).clone(), + value: (*value).clone(), + } + .into()) + } else { + Err(windows::core::Error::from(windows::imp::E_BOUNDS)) + } + } + + fn HasCurrent(&self) -> ::windows::core::Result<bool> { + let mut current = self.current.read().unwrap().clone().peekable(); + + Ok(current.peek().is_some()) + } + + fn MoveNext(&self) -> ::windows::core::Result<bool> { + let mut current = self.current.write().unwrap(); + + current.next(); + Ok(current.clone().peekable().peek().is_some()) + } + + fn GetMany(&self, pairs: &mut [Option<IKeyValuePair<K, V>>]) -> ::windows::core::Result<u32> { + let mut current = self.current.write().unwrap(); + let mut actual = 0; + + for pair in pairs { + if let Some((key, value)) = current.next() { + *pair = Some( + StockKeyValuePair { + key: (*key).clone(), + value: (*value).clone(), + } + .into(), + ); + actual += 1; + } else { + break; + } + } + + Ok(actual as _) + } +} + +#[windows::core::implement(IKeyValuePair<K, V>)] +struct StockKeyValuePair<K, V> +where + K: windows::core::RuntimeType + 'static, + V: windows::core::RuntimeType + 'static, + <K as windows::core::Type<K>>::Default: std::clone::Clone, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + key: K::Default, + value: V::Default, +} + +impl<K, V> IKeyValuePair_Impl<K, V> for StockKeyValuePair<K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + fn Key(&self) -> windows::core::Result<K> { + K::from_default(&self.key) + } + fn Value(&self) -> windows::core::Result<V> { + V::from_default(&self.value) + } +} + +impl<K, V> ::core::convert::TryFrom<std::collections::BTreeMap<K::Default, V::Default>> + for IMapView<K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + type Error = ::windows::core::Error; + fn try_from( + map: std::collections::BTreeMap<K::Default, V::Default>, + ) -> windows::core::Result<Self> { + // TODO: should provide a fallible try_into or more explicit allocator + Ok(StockMapView { map }.into()) + } +} diff --git a/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/VectorView.rs b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/VectorView.rs new file mode 100644 index 000000000..c51dc0c8c --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/VectorView.rs @@ -0,0 +1,132 @@ +#[windows::core::implement(IVectorView<T>, IIterable<T>)] +struct StockVectorView<T> +where + T: windows::core::RuntimeType + 'static, + <T as windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + values: std::vec::Vec<T::Default>, +} + +impl<T> IIterable_Impl<T> for StockVectorView<T> +where + T: windows::core::RuntimeType, + <T as windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + 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(StockVectorViewIterator { + owner: self.cast()?, + current: 0.into(), + } + .into()) + } + } +} + +impl<T> IVectorView_Impl<T> for StockVectorView<T> +where + T: windows::core::RuntimeType, + <T as windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + fn GetAt(&self, index: u32) -> windows::core::Result<T> { + let item = self + .values + .get(index as usize) + .ok_or_else(|| windows::core::Error::from(windows::imp::E_BOUNDS))?; + T::from_default(item) + } + fn Size(&self) -> windows::core::Result<u32> { + Ok(self.values.len() as _) + } + fn IndexOf(&self, value: &T::Default, result: &mut u32) -> windows::core::Result<bool> { + match self.values.iter().position(|element| element == value) { + Some(index) => { + *result = index as _; + Ok(true) + } + None => Ok(false), + } + } + fn GetMany(&self, current: u32, values: &mut [T::Default]) -> windows::core::Result<u32> { + let current = current as usize; + if current >= self.values.len() { + return Ok(0); + } + let actual = std::cmp::min(self.values.len() - current, values.len()); + let (values, _) = values.split_at_mut(actual); + values.clone_from_slice(&self.values[current..current + actual]); + Ok(actual as _) + } +} + +#[::windows::core::implement(IIterator<T>)] +struct StockVectorViewIterator<T> +where + T: ::windows::core::RuntimeType + 'static, + <T as ::windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + owner: IIterable<T>, + current: ::std::sync::atomic::AtomicUsize, +} + +impl<T> IIterator_Impl<T> for StockVectorViewIterator<T> +where + T: ::windows::core::RuntimeType, + <T as ::windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + fn Current(&self) -> ::windows::core::Result<T> { + let owner: &StockVectorView<T> = ::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::core::Error::from(windows::imp::E_BOUNDS)) + } + } + + fn HasCurrent(&self) -> ::windows::core::Result<bool> { + let owner: &StockVectorView<T> = ::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: &StockVectorView<T> = ::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: &StockVectorView<T> = ::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 IVectorView<T> +where + T: ::windows::core::RuntimeType, + <T as ::windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + 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(StockVectorView { values }.into()) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod.rs b/vendor/windows-bindgen/src/extensions/mod.rs new file mode 100644 index 000000000..9b0b6942e --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod.rs @@ -0,0 +1,57 @@ +use super::*; + +pub fn gen_mod(gen: &Gen, namespace: &str) -> TokenStream { + if namespace == "Windows.Win32.UI.WindowsAndMessaging" { + return include_str!("mod/Win32/UI/WindowsAndMessaging/WindowLong.rs").into(); + } + + if gen.sys { + return "".into(); + } + + match namespace { + "Windows.Foundation.Numerics" => concat!( + include_str!("mod/Foundation/Numerics/Matrix3x2.rs"), + include_str!("mod/Foundation/Numerics/Matrix4x4.rs"), + include_str!("mod/Foundation/Numerics/Vector2.rs"), + include_str!("mod/Foundation/Numerics/Vector3.rs"), + include_str!("mod/Foundation/Numerics/Vector4.rs"), + ), + "Windows.Foundation" => concat!( + include_str!("mod/Foundation/IInspectable.rs"), + include_str!("mod/Foundation/PropertyValue.rs"), + include_str!("mod/Foundation/TimeSpan.rs"), + ), + "Windows.Win32.Foundation" => concat!( + include_str!("mod/Win32/Foundation/BOOL.rs"), + include_str!("mod/Win32/Foundation/BOOLEAN.rs"), + include_str!("mod/Win32/Foundation/NTSTATUS.rs"), + include_str!("mod/Win32/Foundation/VARIANT_BOOL.rs"), + include_str!("mod/Win32/Foundation/WIN32_ERROR.rs"), + ), + "Windows.Win32.Networking.WinSock" => concat!( + include_str!("mod/Win32/Networking/WinSock/IN_ADDR.rs"), + include_str!("mod/Win32/Networking/WinSock/IN6_ADDR.rs"), + include_str!("mod/Win32/Networking/WinSock/SOCKADDR_IN.rs"), + include_str!("mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs"), + include_str!("mod/Win32/Networking/WinSock/SOCKADDR_INET.rs"), + ), + "Windows.Win32.UI.WindowsAndMessaging" => { + include_str!("mod/Win32/UI/WindowsAndMessaging/WindowLong.rs") + } + _ => "", + } + .into() +} + +pub fn gen_impl(namespace: &str) -> TokenStream { + match namespace { + "Windows.Foundation.Collections" => concat!( + include_str!("impl/Foundation/Collections/Iterable.rs"), + include_str!("impl/Foundation/Collections/MapView.rs"), + include_str!("impl/Foundation/Collections/VectorView.rs"), + ), + _ => "", + } + .into() +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/IInspectable.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/IInspectable.rs new file mode 100644 index 000000000..c8ddabdbb --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/IInspectable.rs @@ -0,0 +1,13 @@ +impl std::fmt::Debug for windows::core::IInspectable { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // Attempts to retrieve the string representation of the object via the + // IStringable interface. If that fails, it will use the canonical type + // name to give some idea of what the object represents. + let name = + <windows::core::IInspectable as windows::core::ComInterface>::cast::<IStringable>(self) + .and_then(|s| s.ToString()) + .or_else(|_| self.GetRuntimeClassName()) + .unwrap_or_default(); + write!(f, "\"{}\"", name) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix3x2.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix3x2.rs new file mode 100644 index 000000000..98be80636 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix3x2.rs @@ -0,0 +1,139 @@ +impl Matrix3x2 { + pub const fn identity() -> Self { + Self { M11: 1.0, M12: 0.0, M21: 0.0, M22: 1.0, M31: 0.0, M32: 0.0 } + } + pub const fn translation(x: f32, y: f32) -> Self { + Self { M11: 1.0, M12: 0.0, M21: 0.0, M22: 1.0, M31: x, M32: y } + } + pub fn rotation(angle: f32, x: f32, y: f32) -> Self { + #[repr(C)] + pub struct D2D_POINT_2F { + pub x: f32, + pub y: f32, + } + ::windows_targets::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); + } + matrix + } + fn impl_add(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 + rhs.M11, + M12: self.M12 + rhs.M12, + M21: self.M21 + rhs.M21, + M22: self.M22 + rhs.M22, + M31: self.M31 + rhs.M31, + M32: self.M32 + rhs.M32, + } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 - rhs.M11, + M12: self.M12 - rhs.M12, + M21: self.M21 - rhs.M21, + M22: self.M22 - rhs.M22, + M31: self.M31 - rhs.M31, + M32: self.M32 - rhs.M32, + } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 * rhs.M11 + self.M12 * rhs.M21, + M12: self.M11 * rhs.M12 + self.M12 * rhs.M22, + M21: self.M21 * rhs.M11 + self.M22 * rhs.M21, + M22: self.M21 * rhs.M12 + self.M22 * rhs.M22, + M31: self.M31 * rhs.M11 + self.M32 * rhs.M21 + rhs.M31, + M32: self.M31 * rhs.M12 + self.M32 * rhs.M22 + rhs.M32, + } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { M11: self.M11 * rhs, M12: self.M12 * rhs, M21: self.M21 * rhs, M22: self.M22 * rhs, M31: self.M31 * rhs, M32: self.M32 * rhs } + } +} + +impl ::core::ops::Add<Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn add(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn add(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn add(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn add(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn sub(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn sub(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn sub(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn sub(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Mul<Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: f32) -> Matrix3x2 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: f32) -> Matrix3x2 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix4x4.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix4x4.rs new file mode 100644 index 000000000..fb5d60866 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix4x4.rs @@ -0,0 +1,235 @@ +impl Matrix4x4 { + pub const fn translation(x: f32, y: f32, z: f32) -> Self { + Self { + M11: 1.0, + M12: 0.0, + M13: 0.0, + M14: 0.0, + M21: 0.0, + M22: 1.0, + M23: 0.0, + M24: 0.0, + M31: 0.0, + M32: 0.0, + M33: 1.0, + M34: 0.0, + M41: x, + M42: y, + M43: z, + M44: 1.0, + } + } + pub fn rotation_y(degree: f32) -> Self { + ::windows_targets::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; + unsafe { + D2D1SinCos(angle, &mut sin, &mut cos); + } + Self { + M11: cos, + M12: 0.0, + M13: -sin, + M14: 0.0, + M21: 0.0, + M22: 1.0, + M23: 0.0, + M24: 0.0, + M31: sin, + M32: 0.0, + M33: cos, + M34: 0.0, + M41: 0.0, + M42: 0.0, + M43: 0.0, + M44: 1.0, + } + } + pub fn perspective_projection(depth: f32) -> Self { + let projection = if depth > 0.0 { -1.0 / depth } else { 0.0 }; + Self { + M11: 1.0, + M12: 0.0, + M13: 0.0, + M14: 0.0, + M21: 0.0, + M22: 1.0, + M23: 0.0, + M24: 0.0, + M31: 0.0, + M32: 0.0, + M33: 1.0, + M34: projection, + M41: 0.0, + M42: 0.0, + M43: 0.0, + M44: 1.0, + } + } + fn impl_add(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 + rhs.M11, + M12: self.M12 + rhs.M12, + M13: self.M13 + rhs.M13, + M14: self.M14 + rhs.M14, + M21: self.M21 + rhs.M21, + M22: self.M22 + rhs.M22, + M23: self.M23 + rhs.M23, + M24: self.M24 + rhs.M24, + M31: self.M31 + rhs.M31, + M32: self.M32 + rhs.M32, + M33: self.M33 + rhs.M33, + M34: self.M34 + rhs.M34, + M41: self.M41 + rhs.M41, + M42: self.M42 + rhs.M42, + M43: self.M43 + rhs.M43, + M44: self.M44 + rhs.M44, + } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 - rhs.M11, + M12: self.M12 - rhs.M12, + M13: self.M13 - rhs.M13, + M14: self.M14 - rhs.M14, + M21: self.M21 - rhs.M21, + M22: self.M22 - rhs.M22, + M23: self.M23 - rhs.M23, + M24: self.M24 - rhs.M24, + M31: self.M31 - rhs.M31, + M32: self.M32 - rhs.M32, + M33: self.M33 - rhs.M33, + M34: self.M34 - rhs.M34, + M41: self.M41 - rhs.M41, + M42: self.M42 - rhs.M42, + M43: self.M43 - rhs.M43, + M44: self.M44 - rhs.M44, + } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 * rhs.M11 + self.M12 * rhs.M21 + self.M13 * rhs.M31 + self.M14 * rhs.M41, + M12: self.M11 * rhs.M12 + self.M12 * rhs.M22 + self.M13 * rhs.M32 + self.M14 * rhs.M42, + M13: self.M11 * rhs.M13 + self.M12 * rhs.M23 + self.M13 * rhs.M33 + self.M14 * rhs.M43, + M14: self.M11 * rhs.M14 + self.M12 * rhs.M24 + self.M13 * rhs.M34 + self.M14 * rhs.M44, + M21: self.M21 * rhs.M11 + self.M22 * rhs.M21 + self.M23 * rhs.M31 + self.M24 * rhs.M41, + M22: self.M21 * rhs.M12 + self.M22 * rhs.M22 + self.M23 * rhs.M32 + self.M24 * rhs.M42, + M23: self.M21 * rhs.M13 + self.M22 * rhs.M23 + self.M23 * rhs.M33 + self.M24 * rhs.M43, + M24: self.M21 * rhs.M14 + self.M22 * rhs.M24 + self.M23 * rhs.M34 + self.M24 * rhs.M44, + M31: self.M31 * rhs.M11 + self.M32 * rhs.M21 + self.M33 * rhs.M31 + self.M34 * rhs.M41, + M32: self.M31 * rhs.M12 + self.M32 * rhs.M22 + self.M33 * rhs.M32 + self.M34 * rhs.M42, + M33: self.M31 * rhs.M13 + self.M32 * rhs.M23 + self.M33 * rhs.M33 + self.M34 * rhs.M43, + M34: self.M31 * rhs.M14 + self.M32 * rhs.M24 + self.M33 * rhs.M34 + self.M34 * rhs.M44, + M41: self.M41 * rhs.M11 + self.M42 * rhs.M21 + self.M43 * rhs.M31 + self.M44 * rhs.M41, + M42: self.M41 * rhs.M12 + self.M42 * rhs.M22 + self.M43 * rhs.M32 + self.M44 * rhs.M42, + M43: self.M41 * rhs.M13 + self.M42 * rhs.M23 + self.M43 * rhs.M33 + self.M44 * rhs.M43, + M44: self.M41 * rhs.M14 + self.M42 * rhs.M24 + self.M43 * rhs.M34 + self.M44 * rhs.M44, + } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { + M11: self.M11 * rhs, + M12: self.M12 * rhs, + M13: self.M13 * rhs, + M14: self.M14 * rhs, + M21: self.M21 * rhs, + M22: self.M22 * rhs, + M23: self.M23 * rhs, + M24: self.M24 * rhs, + M31: self.M31 * rhs, + M32: self.M32 * rhs, + M33: self.M33 * rhs, + M34: self.M34 * rhs, + M41: self.M41 * rhs, + M42: self.M42 * rhs, + M43: self.M43 * rhs, + M44: self.M44 * rhs, + } + } +} + +impl ::core::ops::Add<Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn add(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn add(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn add(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn add(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn sub(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn sub(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn sub(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn sub(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Mul<Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: f32) -> Matrix4x4 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: f32) -> Matrix4x4 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector2.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector2.rs new file mode 100644 index 000000000..f37b4620b --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector2.rs @@ -0,0 +1,175 @@ +impl Vector2 { + pub fn new(X: f32, Y: f32) -> Self { + Self { X, Y } + } + pub fn zero() -> Self { + Self { X: 0f32, Y: 0f32 } + } + pub fn one() -> Self { + Self { X: 1f32, Y: 1f32 } + } + pub fn unit_x() -> Self { + Self { X: 1.0, Y: 0.0 } + } + pub fn unit_y() -> Self { + Self { X: 0.0, Y: 1.0 } + } + pub fn dot(&self, rhs: &Self) -> f32 { + self.X * rhs.X + self.Y * rhs.Y + } + pub fn length_squared(&self) -> f32 { + self.dot(self) + } + pub fn length(&self) -> f32 { + self.length_squared().sqrt() + } + pub fn distance(&self, value: &Self) -> f32 { + (self - value).length() + } + pub fn distance_squared(&self, value: &Self) -> f32 { + (self - value).length_squared() + } + pub fn normalize(&self) -> Self { + self / self.length() + } + + fn impl_add(&self, rhs: &Self) -> Self { + Self { X: self.X + rhs.X, Y: self.Y + rhs.Y } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { X: self.X - rhs.X, Y: self.Y - rhs.Y } + } + fn impl_div(&self, rhs: &Self) -> Self { + Self { X: self.X / rhs.X, Y: self.Y / rhs.Y } + } + fn impl_div_f32(&self, rhs: f32) -> Self { + Self { X: self.X / rhs, Y: self.Y / rhs } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { X: self.X * rhs.X, Y: self.Y * rhs.Y } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { X: self.X * rhs, Y: self.Y * rhs } + } +} + +impl ::core::ops::Add<Vector2> for Vector2 { + type Output = Vector2; + fn add(self, rhs: Vector2) -> Vector2 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector2> for Vector2 { + type Output = Vector2; + fn add(self, rhs: &Vector2) -> Vector2 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Vector2> for &Vector2 { + type Output = Vector2; + fn add(self, rhs: Vector2) -> Vector2 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector2> for &Vector2 { + type Output = Vector2; + fn add(self, rhs: &Vector2) -> Vector2 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Vector2> for Vector2 { + type Output = Vector2; + fn sub(self, rhs: Vector2) -> Vector2 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector2> for Vector2 { + type Output = Vector2; + fn sub(self, rhs: &Vector2) -> Vector2 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Vector2> for &Vector2 { + type Output = Vector2; + fn sub(self, rhs: Vector2) -> Vector2 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector2> for &Vector2 { + type Output = Vector2; + fn sub(self, rhs: &Vector2) -> Vector2 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Div<Vector2> for Vector2 { + type Output = Vector2; + fn div(self, rhs: Vector2) -> Vector2 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector2> for Vector2 { + type Output = Vector2; + fn div(self, rhs: &Vector2) -> Vector2 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<Vector2> for &Vector2 { + type Output = Vector2; + fn div(self, rhs: Vector2) -> Vector2 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector2> for &Vector2 { + type Output = Vector2; + fn div(self, rhs: &Vector2) -> Vector2 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<f32> for Vector2 { + type Output = Vector2; + fn div(self, rhs: f32) -> Vector2 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Div<f32> for &Vector2 { + type Output = Vector2; + fn div(self, rhs: f32) -> Vector2 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Mul<Vector2> for Vector2 { + type Output = Vector2; + fn mul(self, rhs: Vector2) -> Vector2 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector2> for Vector2 { + type Output = Vector2; + fn mul(self, rhs: &Vector2) -> Vector2 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Vector2> for &Vector2 { + type Output = Vector2; + fn mul(self, rhs: Vector2) -> Vector2 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector2> for &Vector2 { + type Output = Vector2; + fn mul(self, rhs: &Vector2) -> Vector2 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Vector2 { + type Output = Vector2; + fn mul(self, rhs: f32) -> Vector2 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Vector2 { + type Output = Vector2; + fn mul(self, rhs: f32) -> Vector2 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector3.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector3.rs new file mode 100644 index 000000000..58dcf9653 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector3.rs @@ -0,0 +1,178 @@ +impl Vector3 { + pub fn new(X: f32, Y: f32, Z: f32) -> Self { + Self { X, Y, Z } + } + pub fn zero() -> Self { + Self { X: 0f32, Y: 0f32, Z: 0f32 } + } + pub fn one() -> Self { + Self { X: 1f32, Y: 1f32, Z: 1f32 } + } + pub fn unit_x() -> Self { + Self { X: 1.0, Y: 0.0, Z: 0.0 } + } + pub fn unit_y() -> Self { + Self { X: 0.0, Y: 1.0, Z: 0.0 } + } + pub fn unit_z() -> Self { + Self { X: 0.0, Y: 0.0, Z: 1.0 } + } + pub fn dot(&self, rhs: &Self) -> f32 { + self.X * rhs.X + self.Y * rhs.Y + self.Z * rhs.Z + } + pub fn length_squared(&self) -> f32 { + self.dot(self) + } + pub fn length(&self) -> f32 { + self.length_squared().sqrt() + } + pub fn distance(&self, value: &Self) -> f32 { + (self - value).length() + } + pub fn distance_squared(&self, value: &Self) -> f32 { + (self - value).length_squared() + } + pub fn normalize(&self) -> Self { + self / self.length() + } + + fn impl_add(&self, rhs: &Self) -> Self { + Self { X: self.X + rhs.X, Y: self.Y + rhs.Y, Z: self.Z + rhs.Z } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { X: self.X - rhs.X, Y: self.Y - rhs.Y, Z: self.Z - rhs.Z } + } + fn impl_div(&self, rhs: &Self) -> Self { + Self { X: self.X / rhs.X, Y: self.Y / rhs.Y, Z: self.Z / rhs.Z } + } + fn impl_div_f32(&self, rhs: f32) -> Self { + Self { X: self.X / rhs, Y: self.Y / rhs, Z: self.Z / rhs } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { X: self.X * rhs.X, Y: self.Y * rhs.Y, Z: self.Z * rhs.Z } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { X: self.X * rhs, Y: self.Y * rhs, Z: self.Z * rhs } + } +} + +impl ::core::ops::Add<Vector3> for Vector3 { + type Output = Vector3; + fn add(self, rhs: Vector3) -> Vector3 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector3> for Vector3 { + type Output = Vector3; + fn add(self, rhs: &Vector3) -> Vector3 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Vector3> for &Vector3 { + type Output = Vector3; + fn add(self, rhs: Vector3) -> Vector3 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector3> for &Vector3 { + type Output = Vector3; + fn add(self, rhs: &Vector3) -> Vector3 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Vector3> for Vector3 { + type Output = Vector3; + fn sub(self, rhs: Vector3) -> Vector3 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector3> for Vector3 { + type Output = Vector3; + fn sub(self, rhs: &Vector3) -> Vector3 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Vector3> for &Vector3 { + type Output = Vector3; + fn sub(self, rhs: Vector3) -> Vector3 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector3> for &Vector3 { + type Output = Vector3; + fn sub(self, rhs: &Vector3) -> Vector3 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Div<Vector3> for Vector3 { + type Output = Vector3; + fn div(self, rhs: Vector3) -> Vector3 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector3> for Vector3 { + type Output = Vector3; + fn div(self, rhs: &Vector3) -> Vector3 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<Vector3> for &Vector3 { + type Output = Vector3; + fn div(self, rhs: Vector3) -> Vector3 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector3> for &Vector3 { + type Output = Vector3; + fn div(self, rhs: &Vector3) -> Vector3 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<f32> for Vector3 { + type Output = Vector3; + fn div(self, rhs: f32) -> Vector3 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Div<f32> for &Vector3 { + type Output = Vector3; + fn div(self, rhs: f32) -> Vector3 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Mul<Vector3> for Vector3 { + type Output = Vector3; + fn mul(self, rhs: Vector3) -> Vector3 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector3> for Vector3 { + type Output = Vector3; + fn mul(self, rhs: &Vector3) -> Vector3 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Vector3> for &Vector3 { + type Output = Vector3; + fn mul(self, rhs: Vector3) -> Vector3 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector3> for &Vector3 { + type Output = Vector3; + fn mul(self, rhs: &Vector3) -> Vector3 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Vector3 { + type Output = Vector3; + fn mul(self, rhs: f32) -> Vector3 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Vector3 { + type Output = Vector3; + fn mul(self, rhs: f32) -> Vector3 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector4.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector4.rs new file mode 100644 index 000000000..69609d906 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector4.rs @@ -0,0 +1,181 @@ +impl Vector4 { + pub fn new(X: f32, Y: f32, Z: f32, W: f32) -> Self { + Self { X, Y, Z, W } + } + pub fn zero() -> Self { + Self { X: 0f32, Y: 0f32, Z: 0f32, W: 0f32 } + } + pub fn one() -> Self { + Self { X: 1f32, Y: 1f32, Z: 1f32, W: 1f32 } + } + pub fn unit_x() -> Self { + Self { X: 1.0, Y: 0.0, Z: 0.0, W: 0.0 } + } + pub fn unit_y() -> Self { + Self { X: 0.0, Y: 1.0, Z: 0.0, W: 0.0 } + } + pub fn unit_z() -> Self { + Self { X: 0.0, Y: 0.0, Z: 1.0, W: 0.0 } + } + pub fn unit_w() -> Self { + Self { X: 0.0, Y: 0.0, Z: 0.0, W: 1.0 } + } + pub fn dot(&self, rhs: &Self) -> f32 { + self.X * rhs.X + self.Y * rhs.Y + self.Z * rhs.Z + self.W * rhs.W + } + pub fn length_squared(&self) -> f32 { + self.dot(self) + } + pub fn length(&self) -> f32 { + self.length_squared().sqrt() + } + pub fn distance(&self, value: &Self) -> f32 { + (self - value).length() + } + pub fn distance_squared(&self, value: &Self) -> f32 { + (self - value).length_squared() + } + pub fn normalize(&self) -> Self { + self / self.length() + } + + fn impl_add(&self, rhs: &Self) -> Self { + Self { X: self.X + rhs.X, Y: self.Y + rhs.Y, Z: self.Z + rhs.Z, W: self.W + rhs.W } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { X: self.X - rhs.X, Y: self.Y - rhs.Y, Z: self.Z - rhs.Z, W: self.W - rhs.W } + } + fn impl_div(&self, rhs: &Self) -> Self { + Self { X: self.X / rhs.X, Y: self.Y / rhs.Y, Z: self.Z / rhs.Z, W: self.W / rhs.W } + } + fn impl_div_f32(&self, rhs: f32) -> Self { + Self { X: self.X / rhs, Y: self.Y / rhs, Z: self.Z / rhs, W: self.W / rhs } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { X: self.X * rhs.X, Y: self.Y * rhs.Y, Z: self.Z * rhs.Z, W: self.W * rhs.W } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { X: self.X * rhs, Y: self.Y * rhs, Z: self.Z * rhs, W: self.W * rhs } + } +} + +impl ::core::ops::Add<Vector4> for Vector4 { + type Output = Vector4; + fn add(self, rhs: Vector4) -> Vector4 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector4> for Vector4 { + type Output = Vector4; + fn add(self, rhs: &Vector4) -> Vector4 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Vector4> for &Vector4 { + type Output = Vector4; + fn add(self, rhs: Vector4) -> Vector4 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector4> for &Vector4 { + type Output = Vector4; + fn add(self, rhs: &Vector4) -> Vector4 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Vector4> for Vector4 { + type Output = Vector4; + fn sub(self, rhs: Vector4) -> Vector4 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector4> for Vector4 { + type Output = Vector4; + fn sub(self, rhs: &Vector4) -> Vector4 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Vector4> for &Vector4 { + type Output = Vector4; + fn sub(self, rhs: Vector4) -> Vector4 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector4> for &Vector4 { + type Output = Vector4; + fn sub(self, rhs: &Vector4) -> Vector4 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Div<Vector4> for Vector4 { + type Output = Vector4; + fn div(self, rhs: Vector4) -> Vector4 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector4> for Vector4 { + type Output = Vector4; + fn div(self, rhs: &Vector4) -> Vector4 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<Vector4> for &Vector4 { + type Output = Vector4; + fn div(self, rhs: Vector4) -> Vector4 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector4> for &Vector4 { + type Output = Vector4; + fn div(self, rhs: &Vector4) -> Vector4 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<f32> for Vector4 { + type Output = Vector4; + fn div(self, rhs: f32) -> Vector4 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Div<f32> for &Vector4 { + type Output = Vector4; + fn div(self, rhs: f32) -> Vector4 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Mul<Vector4> for Vector4 { + type Output = Vector4; + fn mul(self, rhs: Vector4) -> Vector4 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector4> for Vector4 { + type Output = Vector4; + fn mul(self, rhs: &Vector4) -> Vector4 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Vector4> for &Vector4 { + type Output = Vector4; + fn mul(self, rhs: Vector4) -> Vector4 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector4> for &Vector4 { + type Output = Vector4; + fn mul(self, rhs: &Vector4) -> Vector4 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Vector4 { + type Output = Vector4; + fn mul(self, rhs: f32) -> Vector4 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Vector4 { + type Output = Vector4; + fn mul(self, rhs: f32) -> Vector4 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/PropertyValue.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/PropertyValue.rs new file mode 100644 index 000000000..d9a1f113e --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/PropertyValue.rs @@ -0,0 +1,71 @@ +macro_rules! primitive_boxed_type { + ($(($t:ty, $m:ident)),+) => { + $(impl std::convert::TryFrom<$t> for windows::core::IInspectable { + type Error = windows::core::Error; + fn try_from(value: $t) -> windows::core::Result<Self> { + PropertyValue::$m(value) + } + } + impl std::convert::TryFrom<windows::core::IInspectable> for $t { + type Error = windows::core::Error; + fn try_from(value: windows::core::IInspectable) -> windows::core::Result<Self> { + <windows::core::IInspectable as windows::core::ComInterface>::cast::<IReference<$t>>(&value)?.Value() + } + } + impl std::convert::TryFrom<&windows::core::IInspectable> for $t { + type Error = windows::core::Error; + fn try_from(value: &windows::core::IInspectable) -> windows::core::Result<Self> { + <windows::core::IInspectable as windows::core::ComInterface>::cast::<IReference<$t>>(value)?.Value() + } + })* + }; +} +primitive_boxed_type! { + (bool, CreateBoolean), + (u8, CreateUInt8), + (i16, CreateInt16), + (u16, CreateUInt16), + (i32, CreateInt32), + (u32, CreateUInt32), + (i64, CreateInt64), + (u64, CreateUInt64), + (f32, CreateSingle), + (f64, CreateDouble) +} +impl std::convert::TryFrom<&str> for windows::core::IInspectable { + type Error = windows::core::Error; + fn try_from(value: &str) -> windows::core::Result<Self> { + let value: windows::core::HSTRING = value.into(); + PropertyValue::CreateString(&value) + } +} +impl std::convert::TryFrom<windows::core::HSTRING> for windows::core::IInspectable { + type Error = windows::core::Error; + fn try_from(value: windows::core::HSTRING) -> windows::core::Result<Self> { + PropertyValue::CreateString(&value) + } +} +impl std::convert::TryFrom<&windows::core::HSTRING> for windows::core::IInspectable { + type Error = windows::core::Error; + fn try_from(value: &windows::core::HSTRING) -> windows::core::Result<Self> { + PropertyValue::CreateString(value) + } +} +impl std::convert::TryFrom<windows::core::IInspectable> for windows::core::HSTRING { + type Error = windows::core::Error; + fn try_from(value: windows::core::IInspectable) -> windows::core::Result<Self> { + <windows::core::IInspectable as windows::core::ComInterface>::cast::< + IReference<windows::core::HSTRING>, + >(&value)? + .Value() + } +} +impl std::convert::TryFrom<&windows::core::IInspectable> for windows::core::HSTRING { + type Error = windows::core::Error; + fn try_from(value: &windows::core::IInspectable) -> windows::core::Result<Self> { + <windows::core::IInspectable as windows::core::ComInterface>::cast::< + IReference<windows::core::HSTRING>, + >(value)? + .Value() + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/TimeSpan.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/TimeSpan.rs new file mode 100644 index 000000000..814b3d45b --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/TimeSpan.rs @@ -0,0 +1,10 @@ +impl ::core::convert::From<::core::time::Duration> for TimeSpan { + fn from(value: ::core::time::Duration) -> Self { + Self { Duration: (value.as_nanos() / 100) as i64 } + } +} +impl ::core::convert::From<TimeSpan> for ::core::time::Duration { + fn from(value: TimeSpan) -> Self { + ::core::time::Duration::from_nanos((value.Duration * 100) as u64) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOL.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOL.rs new file mode 100644 index 000000000..f09ae9111 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOL.rs @@ -0,0 +1,73 @@ +impl BOOL { + #[inline] + pub fn as_bool(self) -> bool { + self.0 != 0 + } + #[inline] + pub fn ok(self) -> ::windows::core::Result<()> { + if self.as_bool() { + Ok(()) + } else { + Err(::windows::core::Error::from_win32()) + } + } + #[inline] + #[track_caller] + pub fn unwrap(self) { + self.ok().unwrap(); + } + #[inline] + #[track_caller] + pub fn expect(self, msg: &str) { + self.ok().expect(msg); + } +} +impl ::core::convert::From<BOOL> for bool { + fn from(value: BOOL) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<&BOOL> for bool { + fn from(value: &BOOL) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<bool> for BOOL { + fn from(value: bool) -> Self { + if value { + Self(1) + } else { + Self(0) + } + } +} +impl ::core::convert::From<&bool> for BOOL { + fn from(value: &bool) -> Self { + (*value).into() + } +} +impl ::core::cmp::PartialEq<bool> for BOOL { + fn eq(&self, other: &bool) -> bool { + self.as_bool() == *other + } +} +impl ::core::cmp::PartialEq<BOOL> for bool { + fn eq(&self, other: &BOOL) -> bool { + *self == other.as_bool() + } +} +impl ::core::ops::Not for BOOL { + type Output = Self; + fn not(self) -> Self::Output { + if self.as_bool() { + Self(0) + } else { + Self(1) + } + } +} +impl windows::core::IntoParam<BOOL> for bool { + fn into_param(self) -> windows::core::Param<BOOL> { + windows::core::Param::Owned(self.into()) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOLEAN.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOLEAN.rs new file mode 100644 index 000000000..44afc65c2 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOLEAN.rs @@ -0,0 +1,68 @@ +impl BOOLEAN { + #[inline] + pub fn as_bool(self) -> bool { + self.0 != 0 + } + #[inline] + pub fn ok(self) -> ::windows::core::Result<()> { + if self.as_bool() { + Ok(()) + } else { + Err(::windows::core::Error::from_win32()) + } + } + #[inline] + #[track_caller] + pub fn unwrap(self) { + self.ok().unwrap(); + } + #[inline] + #[track_caller] + pub fn expect(self, msg: &str) { + self.ok().expect(msg); + } +} +impl ::core::convert::From<BOOLEAN> for bool { + fn from(value: BOOLEAN) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<&BOOLEAN> for bool { + fn from(value: &BOOLEAN) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<bool> for BOOLEAN { + fn from(value: bool) -> Self { + if value { + Self(1) + } else { + Self(0) + } + } +} +impl ::core::convert::From<&bool> for BOOLEAN { + fn from(value: &bool) -> Self { + (*value).into() + } +} +impl ::core::cmp::PartialEq<bool> for BOOLEAN { + fn eq(&self, other: &bool) -> bool { + self.as_bool() == *other + } +} +impl ::core::cmp::PartialEq<BOOLEAN> for bool { + fn eq(&self, other: &BOOLEAN) -> bool { + *self == other.as_bool() + } +} +impl ::core::ops::Not for BOOLEAN { + type Output = Self; + fn not(self) -> Self::Output { + if self.as_bool() { + Self(0) + } else { + Self(1) + } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/NTSTATUS.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/NTSTATUS.rs new file mode 100644 index 000000000..66d77db19 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/NTSTATUS.rs @@ -0,0 +1,32 @@ +impl NTSTATUS { + #[inline] + pub const fn is_ok(self) -> bool { + self.0 >= 0 + } + #[inline] + pub const fn is_err(self) -> bool { + !self.is_ok() + } + #[inline] + pub const fn to_hresult(self) -> ::windows::core::HRESULT { + ::windows::core::HRESULT(self.0 | 0x1000_0000) + } + #[inline] + pub const fn ok(self) -> ::windows::core::Result<()> { + if self.is_ok() { + Ok(()) + } else { + Err(::windows::core::Error { code: self.to_hresult(), info: None }) + } + } +} +impl ::core::convert::From<NTSTATUS> for ::windows::core::HRESULT { + fn from(value: NTSTATUS) -> Self { + value.to_hresult() + } +} +impl ::core::convert::From<NTSTATUS> for ::windows::core::Error { + fn from(value: NTSTATUS) -> Self { + Self { code: value.to_hresult(), info: None } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs new file mode 100644 index 000000000..3015224ef --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs @@ -0,0 +1,68 @@ +impl VARIANT_BOOL { + #[inline] + pub fn as_bool(self) -> bool { + self.0 != 0 + } + #[inline] + pub fn ok(self) -> ::windows::core::Result<()> { + if self.as_bool() { + Ok(()) + } else { + Err(::windows::core::Error::from_win32()) + } + } + #[inline] + #[track_caller] + pub fn unwrap(self) { + self.ok().unwrap(); + } + #[inline] + #[track_caller] + pub fn expect(self, msg: &str) { + self.ok().expect(msg); + } +} +impl ::core::convert::From<VARIANT_BOOL> for bool { + fn from(value: VARIANT_BOOL) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<&VARIANT_BOOL> for bool { + fn from(value: &VARIANT_BOOL) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<bool> for VARIANT_BOOL { + fn from(value: bool) -> Self { + if value { + VARIANT_TRUE + } else { + VARIANT_FALSE + } + } +} +impl ::core::convert::From<&bool> for VARIANT_BOOL { + fn from(value: &bool) -> Self { + (*value).into() + } +} +impl ::core::cmp::PartialEq<bool> for VARIANT_BOOL { + fn eq(&self, other: &bool) -> bool { + self.as_bool() == *other + } +} +impl ::core::cmp::PartialEq<VARIANT_BOOL> for bool { + fn eq(&self, other: &VARIANT_BOOL) -> bool { + *self == other.as_bool() + } +} +impl ::core::ops::Not for VARIANT_BOOL { + type Output = Self; + fn not(self) -> Self::Output { + if self.as_bool() { + VARIANT_FALSE + } else { + VARIANT_TRUE + } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/WIN32_ERROR.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/WIN32_ERROR.rs new file mode 100644 index 000000000..d875953b2 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/WIN32_ERROR.rs @@ -0,0 +1,41 @@ +impl WIN32_ERROR { + #[inline] + pub const fn is_ok(self) -> bool { + self.0 == 0 + } + #[inline] + pub const fn is_err(self) -> bool { + !self.is_ok() + } + #[inline] + pub const fn to_hresult(self) -> ::windows::core::HRESULT { + ::windows::core::HRESULT(if self.0 == 0 { self.0 } else { (self.0 & 0x0000_FFFF) | (7 << 16) | 0x8000_0000 } as _) + } + #[inline] + pub fn from_error(error: &::windows::core::Error) -> ::core::option::Option<Self> { + let hresult = error.code().0 as u32; + if ((hresult >> 16) & 0x7FF) == 7 { + Some(Self(hresult & 0xFFFF)) + } else { + None + } + } + #[inline] + pub const fn ok(self) -> ::windows::core::Result<()> { + if self.is_ok() { + Ok(()) + } else { + Err(::windows::core::Error { code: self.to_hresult(), info: None }) + } + } +} +impl ::core::convert::From<WIN32_ERROR> for ::windows::core::HRESULT { + fn from(value: WIN32_ERROR) -> Self { + value.to_hresult() + } +} +impl ::core::convert::From<WIN32_ERROR> for ::windows::core::Error { + fn from(value: WIN32_ERROR) -> Self { + Self { code: value.to_hresult(), info: None } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs new file mode 100644 index 000000000..f4290fba6 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs @@ -0,0 +1,11 @@ +impl ::core::convert::From<::std::net::Ipv6Addr> for IN6_ADDR { + fn from(addr: ::std::net::Ipv6Addr) -> Self { + Self { u: IN6_ADDR_0 { Byte: addr.octets() } } + } +} +impl ::core::convert::From<IN6_ADDR> for ::std::net::Ipv6Addr { + fn from(in6_addr: IN6_ADDR) -> Self { + // SAFETY: this is safe because the union variants are just views of the same exact data + Self::from(unsafe { in6_addr.u.Byte }) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs new file mode 100644 index 000000000..d12af968b --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs @@ -0,0 +1,15 @@ +impl ::core::convert::From<::std::net::Ipv4Addr> for IN_ADDR { + fn from(addr: ::std::net::Ipv4Addr) -> Self { + // u32::from(addr) is in host byte order + // S_addr must be big-endian, network byte order + Self { S_un: IN_ADDR_0 { S_addr: u32::from(addr).to_be() } } + } +} +impl ::core::convert::From<IN_ADDR> for ::std::net::Ipv4Addr { + fn from(in_addr: IN_ADDR) -> Self { + // SAFETY: this is safe because the union variants are just views of the same exact data + // in_addr.S_un.S_addr is big-endian, network byte order + // Ipv4Addr::new() expects the parameter in host byte order + Self::from(u32::from_be(unsafe { in_addr.S_un.S_addr })) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs new file mode 100644 index 000000000..68bfdc76d --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs @@ -0,0 +1,7 @@ +impl ::core::convert::From<::std::net::SocketAddrV4> for SOCKADDR_IN { + fn from(addr: ::std::net::SocketAddrV4) -> Self { + // addr.port() is in host byte order + // sin_port must be big-endian, network byte order + SOCKADDR_IN { sin_family: AF_INET, sin_port: addr.port().to_be(), sin_addr: (*addr.ip()).into(), ..Default::default() } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs new file mode 100644 index 000000000..7b76f2f7d --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs @@ -0,0 +1,15 @@ +impl ::core::convert::From<::std::net::SocketAddrV6> for SOCKADDR_IN6 { + fn from(addr: ::std::net::SocketAddrV6) -> Self { + // addr.port() and addr.flowinfo() are in host byte order + // sin6_port and sin6_flowinfo must be big-endian, network byte order + // sin6_scope_id is a bitfield without endianness + SOCKADDR_IN6 { + sin6_family: AF_INET6, + sin6_port: addr.port().to_be(), + sin6_flowinfo: addr.flowinfo().to_be(), + sin6_addr: (*addr.ip()).into(), + Anonymous: SOCKADDR_IN6_0 { sin6_scope_id: addr.scope_id() }, + ..Default::default() + } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs new file mode 100644 index 000000000..ccaf570c0 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs @@ -0,0 +1,19 @@ + +impl ::core::convert::From<::std::net::SocketAddrV4> for SOCKADDR_INET { + fn from(addr: ::std::net::SocketAddrV4) -> Self { + SOCKADDR_INET { Ipv4: addr.into() } + } +} +impl ::core::convert::From<::std::net::SocketAddrV6> for SOCKADDR_INET { + fn from(addr: ::std::net::SocketAddrV6) -> Self { + SOCKADDR_INET { Ipv6: addr.into() } + } +} +impl ::core::convert::From<::std::net::SocketAddr> for SOCKADDR_INET { + fn from(addr: ::std::net::SocketAddr) -> Self { + match addr { + ::std::net::SocketAddr::V4(socket_addr_v4) => socket_addr_v4.into(), + ::std::net::SocketAddr::V6(socket_addr_v6) => socket_addr_v6.into(), + } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs new file mode 100644 index 000000000..cf1cc08d9 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs @@ -0,0 +1,12 @@ +#[cfg(target_pointer_width = "32")] +#[cfg(feature = "Win32_Foundation")] +pub use GetWindowLongA as GetWindowLongPtrA; +#[cfg(target_pointer_width = "32")] +#[cfg(feature = "Win32_Foundation")] +pub use GetWindowLongW as GetWindowLongPtrW; +#[cfg(target_pointer_width = "32")] +#[cfg(feature = "Win32_Foundation")] +pub use SetWindowLongA as SetWindowLongPtrA; +#[cfg(target_pointer_width = "32")] +#[cfg(feature = "Win32_Foundation")] +pub use SetWindowLongW as SetWindowLongPtrW; diff --git a/vendor/windows-bindgen/src/functions.rs b/vendor/windows-bindgen/src/functions.rs new file mode 100644 index 000000000..f5ec866bb --- /dev/null +++ b/vendor/windows-bindgen/src/functions.rs @@ -0,0 +1,285 @@ +use super::*; + +pub fn gen(gen: &Gen, def: MethodDef) -> TokenStream { + if gen.sys { + gen_sys_function(gen, def) + } else { + gen_win_function(gen, def) + } +} + +fn gen_sys_function(gen: &Gen, def: MethodDef) -> TokenStream { + let signature = gen.reader.method_def_signature(def, &[]); + let cfg = gen.reader.signature_cfg(&signature); + let mut tokens = gen.cfg_features(&cfg); + tokens.combine(&gen_link(gen, &signature, &cfg)); + tokens +} + +fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { + let name = to_ident(gen.reader.method_def_name(def)); + let signature = gen.reader.method_def_signature(def, &[]); + let generics = gen.constraint_generics(&signature.params); + let where_clause = gen.where_clause(&signature.params); + let abi_return_type = gen.return_sig(&signature); + let cfg = gen.reader.signature_cfg(&signature); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + let link = gen_link(gen, &signature, &cfg); + + let kind = gen.reader.signature_kind(&signature); + match kind { + SignatureKind::Query(_) => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let generics = expand_generics(generics, quote!(T)); + let where_clause = + expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface)); + + quote! { + #doc + #features + #[inline] + 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__) + } + } + } + SignatureKind::QueryOptional(_) => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let generics = expand_generics(generics, quote!(T)); + let where_clause = + expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface)); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params result__: *mut ::core::option::Option<T>) -> ::windows::core::Result<()> #where_clause { + #link + #name(#args).ok() + } + } + } + SignatureKind::ResultValue => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let return_type = gen.type_name(&return_type); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause { + #link + let mut result__ = ::windows::core::zeroed::<#return_type>(); + #name(#args).from_abi(result__) + } + } + } + SignatureKind::ResultVoid => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<()> #where_clause { + #link + #name(#args).ok() + } + } + } + SignatureKind::ReturnValue => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let is_nullable = gen.reader.type_is_nullable(&return_type); + let return_type = gen.type_name(&return_type); + + if is_nullable { + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause { + #link + let mut result__ = ::windows::core::zeroed::<#return_type>(); + #name(#args); + ::windows::core::from_abi(result__.assume_init()) + } + } + } else { + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> #return_type #where_clause { + #link + let mut result__ = ::windows::core::zeroed::<#return_type>(); + #name(#args); + ::std::mem::transmute(result__) + } + } + } + } + SignatureKind::ReturnStruct | SignatureKind::PreserveSig => { + if handle_last_error(gen, def, &signature) { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = gen.type_name(&signature.return_type.unwrap()); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause { + #link + let result__ = #name(#args); + ::windows::imp::then(!result__.is_invalid(), ||result__).ok_or_else(::windows::core::Error::from_win32) + } + } + } else { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) #abi_return_type #where_clause { + #link + #name(#args) + } + } + } + } + SignatureKind::ReturnVoid => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let does_not_return = does_not_return(gen, def); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) #does_not_return #where_clause { + #link + #name(#args) + } + } + } + } +} + +fn gen_link(gen: &Gen, signature: &Signature, cfg: &Cfg) -> TokenStream { + let name = gen.reader.method_def_name(signature.def); + let ident = to_ident(name); + let library = gen.reader.method_def_module_name(signature.def); + let abi = gen.reader.method_def_extern_abi(signature.def); + + let symbol = if let Some(impl_map) = gen.reader.method_def_impl_map(signature.def) { + gen.reader.impl_map_import_name(impl_map) + } else { + name + }; + + let link_name = if symbol != name { + quote! { #[link_name = #symbol] } + } else { + quote! {} + }; + + let params = signature.params.iter().map(|p| { + let name = gen.param_name(p.def); + let tokens = if p.kind == SignatureParamKind::ValueType { + gen.type_default_name(&p.ty) + } else { + gen.type_abi_name(&p.ty) + }; + quote! { #name: #tokens } + }); + + let return_type = gen.return_sig(signature); + + if gen.std || !gen.namespace.starts_with("Windows.") { + let library = library.trim_end_matches(".dll"); + + quote! { + #[link(name = #library)] + extern #abi { + #link_name + pub fn #ident(#(#params),*) #return_type; + } + } + } else if let Some(library) = gen.reader.method_def_static_lib(signature.def) { + quote! { + #[link(name = #library, kind = "static")] + extern #abi { + #link_name + pub fn #ident(#(#params),*) #return_type; + } + } + } else { + let symbol = if symbol != name { + format!(" \"{symbol}\"") + } else { + String::new() + }; + + let doc = if gen.sys { + gen.cfg_doc(cfg).0 + } else { + String::new() + }; + + let mut tokens = String::new(); + for param in params { + tokens.push_str(&format!("{}, ", param.as_str())); + } + let tokens = tokens.trim_end_matches(", "); + format!( + r#"::windows_targets::link!("{library}" "{abi}"{symbol}{doc} fn {name}({tokens}){return_type});"# + ) + .into() + } +} + +fn does_not_return(gen: &Gen, def: MethodDef) -> TokenStream { + if gen.reader.method_def_does_not_return(def) { + quote! { -> ! } + } else { + quote! {} + } +} + +fn handle_last_error(gen: &Gen, def: MethodDef, signature: &Signature) -> bool { + if let Some(map) = gen.reader.method_def_impl_map(def) { + if gen + .reader + .impl_map_flags(map) + .contains(PInvokeAttributes::LAST_ERROR) + { + if let Some(Type::TypeDef((return_type, _))) = &signature.return_type { + if gen.reader.type_def_is_handle(*return_type) { + if gen + .reader + .type_def_underlying_type(*return_type) + .is_pointer() + { + return true; + } + if !gen.reader.type_def_invalid_values(*return_type).is_empty() { + return true; + } + } + } + } + } + false +} diff --git a/vendor/windows-bindgen/src/gen.rs b/vendor/windows-bindgen/src/gen.rs new file mode 100644 index 000000000..30d4150e6 --- /dev/null +++ b/vendor/windows-bindgen/src/gen.rs @@ -0,0 +1,1400 @@ +use super::*; + +pub struct Gen<'a> { + pub reader: &'a Reader<'a>, + pub namespace: &'a str, + pub sys: bool, + pub cfg: bool, + pub doc: bool, + pub component: bool, + pub standalone: bool, + pub std: bool, +} + +impl<'a> Gen<'a> { + pub fn new(reader: &'a Reader) -> Self { + Self { + reader, + namespace: "", + sys: false, + cfg: false, + doc: false, + component: false, + standalone: false, + std: false, + } + } + + // + // TypeDef + // + + pub fn type_def_name(&self, def: TypeDef, generics: &[Type]) -> TokenStream { + self.type_def_name_imp(def, generics, "") + } + pub fn type_def_vtbl_name(&self, def: TypeDef, generics: &[Type]) -> TokenStream { + self.type_def_name_imp(def, generics, "_Vtbl") + } + pub fn type_def_name_imp(&self, def: TypeDef, generics: &[Type], suffix: &str) -> TokenStream { + let type_name = self.reader.type_def_type_name(def); + + if type_name.namespace.is_empty() { + to_ident(&self.scoped_name(def)) + } else { + let mut namespace = self.namespace(type_name.namespace); + let mut name = to_ident(type_name.name); + name.push_str(suffix); + + if generics.is_empty() || self.sys { + namespace.combine(&name); + namespace + } else { + let colon_separated = if !namespace.as_str().is_empty() { + quote! { :: } + } else { + quote! {} + }; + + let generics = generics.iter().map(|ty| self.type_name(ty)); + quote! { #namespace #name #colon_separated<#(#generics),*> } + } + } + } + + // + // Type + // + + pub fn type_default_name(&self, ty: &Type) -> TokenStream { + if let Type::WinrtArray(ty) = ty { + self.type_default_name(ty) + } else { + let kind = self.type_name(ty); + + if ty.is_generic() { + quote! { <#kind as ::windows::core::Type<#kind>>::Default } + } else if self.reader.type_is_nullable(ty) && !self.sys { + quote! { ::core::option::Option<#kind> } + } else { + kind + } + } + } + + pub(crate) fn type_name(&self, ty: &Type) -> TokenStream { + match ty { + Type::Void => quote! { ::core::ffi::c_void }, + Type::Bool => quote! { bool }, + Type::Char => quote! { u16 }, + Type::I8 => quote! { i8 }, + Type::U8 => quote! { u8 }, + Type::I16 => quote! { i16 }, + Type::U16 => quote! { u16 }, + Type::I32 => quote! { i32 }, + Type::U32 => quote! { u32 }, + Type::I64 => quote! { i64 }, + Type::U64 => quote! { u64 }, + Type::F32 => quote! { f32 }, + Type::F64 => quote! { f64 }, + Type::ISize => quote! { isize }, + Type::USize => quote! { usize }, + Type::String => { + let crate_name = self.crate_name(); + quote! { #crate_name HSTRING } + } + Type::BSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name BSTR } + } + Type::IInspectable => { + let crate_name = self.crate_name(); + quote! { #crate_name IInspectable } + } + Type::GUID => { + let crate_name = self.crate_name(); + quote! { #crate_name GUID } + } + Type::IUnknown => { + let crate_name = self.crate_name(); + quote! { #crate_name IUnknown } + } + Type::HRESULT => { + let crate_name = self.crate_name(); + quote! { #crate_name HRESULT } + } + Type::PSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name PSTR } + } + Type::PWSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name PWSTR } + } + Type::PCSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name PCSTR } + } + Type::PCWSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name PCWSTR } + } + Type::Win32Array((ty, len)) => { + let name = self.type_default_name(ty); + let len = Literal::usize_unsuffixed(*len); + quote! { [#name; #len] } + } + Type::GenericParam(generic) => self.reader.generic_param_name(*generic).into(), + Type::TypeDef((def, generics)) => self.type_def_name(*def, generics), + Type::MutPtr((ty, pointers)) => { + let pointers = mut_ptrs(*pointers); + let ty = self.type_default_name(ty); + quote! { #pointers #ty } + } + Type::ConstPtr((ty, pointers)) => { + let pointers = const_ptrs(*pointers); + let ty = self.type_default_name(ty); + quote! { #pointers #ty } + } + Type::WinrtArray(ty) => self.type_name(ty), + Type::WinrtArrayRef(ty) => self.type_name(ty), + Type::WinrtConstRef(ty) => self.type_name(ty), + _ => unimplemented!(), + } + } + pub fn type_vtbl_name(&self, ty: &Type) -> TokenStream { + match ty { + Type::TypeDef((def, generics)) => self.type_def_vtbl_name(*def, generics), + _ => unimplemented!(), + } + } + pub fn type_abi_name(&self, ty: &Type) -> TokenStream { + if self.sys { + return self.type_default_name(ty); + } + + match ty { + Type::IUnknown | Type::IInspectable => { + quote! { *mut ::core::ffi::c_void } + } + Type::String => { + quote! { ::std::mem::MaybeUninit<::windows::core::HSTRING> } + } + Type::BSTR => { + quote! { ::std::mem::MaybeUninit<::windows::core::BSTR> } + } + Type::Win32Array((kind, len)) => { + let name = self.type_abi_name(kind); + let len = Literal::usize_unsuffixed(*len); + quote! { [#name; #len] } + } + Type::GenericParam(generic) => { + let name = to_ident(self.reader.generic_param_name(*generic)); + quote! { ::windows::core::AbiType<#name> } + } + Type::TypeDef((def, _)) => match self.reader.type_def_kind(*def) { + TypeKind::Enum => self.type_def_name(*def, &[]), + TypeKind::Struct => { + let tokens = self.type_def_name(*def, &[]); + if self.reader.type_def_is_blittable(*def) { + tokens + } else { + quote! { ::std::mem::MaybeUninit<#tokens> } + } + } + TypeKind::Delegate => { + if self + .reader + .type_def_flags(*def) + .contains(TypeAttributes::WINRT) + { + quote! { *mut ::core::ffi::c_void } + } else { + self.type_def_name(*def, &[]) + } + } + _ => quote! { *mut ::core::ffi::c_void }, + }, + Type::MutPtr((kind, pointers)) => { + let pointers_tokens = gen_mut_ptrs(*pointers); + let kind = if *pointers > 1 { + self.type_name(kind) + } else { + self.type_abi_name(kind) + }; + quote! { #pointers_tokens #kind } + } + Type::ConstPtr((kind, pointers)) => { + let pointers_tokens = gen_const_ptrs(*pointers); + let kind = if *pointers > 1 { + self.type_name(kind) + } else { + self.type_abi_name(kind) + }; + quote! { #pointers_tokens #kind } + } + Type::WinrtArray(kind) => self.type_abi_name(kind), + Type::WinrtArrayRef(kind) => self.type_abi_name(kind), + _ => self.type_name(ty), + } + } + + // + // Constraints + // + + pub fn generic_phantoms(&self, generics: &[Type]) -> TokenStream { + let mut tokens = TokenStream::new(); + for generic in generics { + let generic = self.type_name(generic); + tokens.combine("e! { ::core::marker::PhantomData::<#generic>, }); + } + tokens + } + pub fn generic_named_phantoms(&self, generics: &[Type]) -> Vec<TokenStream> { + generics + .iter() + .map(|generic| { + let generic = self.type_name(generic); + quote! { #generic: ::core::marker::PhantomData::<#generic>, } + }) + .collect() + } + pub fn generic_constraints(&self, generics: &[Type]) -> TokenStream { + let mut tokens = TokenStream::new(); + for generic in generics { + let generic = self.type_name(generic); + tokens.combine("e! { #generic: ::windows::core::RuntimeType + 'static, }); + } + tokens + } + pub fn generic_names(&self, generics: &[Type]) -> TokenStream { + let mut tokens = TokenStream::new(); + for generic in generics { + let generic = self.type_name(generic); + tokens.combine("e! { #generic, }); + } + tokens + } + /// The signature params which are generic (along with their relative index) + pub fn generic_params<'b>( + &'b self, + params: &'b [SignatureParam], + ) -> impl Iterator<Item = (usize, &SignatureParam)> + 'b { + params + .iter() + .filter(move |param| self.reader.signature_param_is_convertible(param)) + .enumerate() + } + /// The generic param names (i.e., `T` in `fn foo<T>()`) + pub fn constraint_generics(&self, params: &[SignatureParam]) -> TokenStream { + let mut generics = self + .generic_params(params) + .map(|(position, _)| -> TokenStream { format!("P{position}").into() }) + .peekable(); + + if generics.peek().is_some() { + quote!(#(#generics),*) + } else { + TokenStream::new() + } + } + /// A `where` clause for some constrained generic params + pub fn where_clause(&self, params: &[SignatureParam]) -> TokenStream { + let constraints = self.param_constraints(params); + + if !constraints.is_empty() { + quote!(where #constraints) + } else { + quote!() + } + } + fn param_constraints(&self, params: &[SignatureParam]) -> TokenStream { + let mut tokens = TokenStream::new(); + let gen_name = |position| { + let name: TokenStream = format!("P{position}").into(); + name + }; + for (position, param) in self.generic_params(params) { + match param.kind { + SignatureParamKind::TryInto => { + let name: TokenStream = gen_name(position); + let into = self.type_name(¶m.ty); + tokens.combine("e! { #name: ::windows::core::TryIntoParam<#into>, }); + } + SignatureParamKind::IntoParam => { + let name: TokenStream = gen_name(position); + let into = self.type_name(¶m.ty); + tokens.combine("e! { #name: ::windows::core::IntoParam<#into>, }); + } + _ => {} + } + } + tokens + } + + // + // Cfg + // + + /// Generates doc comments for types, free functions, and constants. + pub(crate) fn cfg_doc(&self, cfg: &Cfg) -> TokenStream { + if !self.doc { + quote! {} + } else { + let mut tokens = format!(r#"`\"{}\"`"#, to_feature(self.namespace)); + let features = self.cfg_features_imp(cfg, self.namespace); + + for features in features { + write!(tokens, r#", `\"{}\"`"#, to_feature(features)).unwrap(); + } + + if cfg.implement { + tokens.push_str(r#", `\"implement\"`"#) + } + + format!(r#" #[doc = "*Required features: {tokens}*"]"#).into() + } + } + + /// Generates doc comments for member functions (methods) and avoids redundantly declaring the + /// enclosing module feature required by the method's type. + pub(crate) fn cfg_method_doc(&self, cfg: &Cfg) -> TokenStream { + if !self.doc { + quote! {} + } else { + let features = self.cfg_features_imp(cfg, self.namespace); + if features.is_empty() { + quote! {} + } else { + let mut tokens = String::new(); + for features in features { + write!(tokens, r#"`\"{}\"`, "#, to_feature(features)).unwrap(); + } + tokens.truncate(tokens.len() - 2); + format!(r#"#[doc = "*Required features: {tokens}*"]"#).into() + } + } + } + + pub(crate) fn cfg_features(&self, cfg: &Cfg) -> TokenStream { + let arches = &cfg.arches; + let arch = match arches.len() { + 0 => quote! {}, + 1 => { + quote! { #[cfg(#(target_arch = #arches),*)] } + } + _ => { + quote! { #[cfg(any(#(target_arch = #arches),*))] } + } + }; + + let features = self.cfg_features_imp(cfg, self.namespace); + + let features = match features.len() { + 0 => quote! {}, + 1 => { + let features = features.iter().cloned().map(to_feature); + quote! { #[cfg(#(feature = #features)*)] } + } + _ => { + let features = features.iter().cloned().map(to_feature); + quote! { #[cfg(all( #(feature = #features),* ))] } + } + }; + + quote! { #arch #features } + } + + fn cfg_features_imp(&self, cfg: &'a Cfg, namespace: &'a str) -> Vec<&'a str> { + let mut compact = Vec::<&'static str>::new(); + if !self.standalone && !self.component { + for feature in cfg.types.keys() { + if !feature.is_empty() && !starts_with(namespace, feature) { + for pos in 0..compact.len() { + if starts_with(feature, unsafe { compact.get_unchecked(pos) }) { + compact.remove(pos); + break; + } + } + compact.push(feature); + } + } + } + compact + } + + fn cfg_not_features(&self, cfg: &Cfg) -> TokenStream { + let features = self.cfg_features_imp(cfg, self.namespace); + if features.is_empty() { + quote! {} + } else { + match features.len() { + 0 => quote! {}, + 1 => { + let features = features.iter().cloned().map(to_feature); + quote! { #[cfg(not(#(feature = #features)*))] } + } + _ => { + let features = features.iter().cloned().map(to_feature); + quote! { #[cfg(not(all( #(feature = #features),* )))] } + } + } + } + } + + // + // Other helpers + // + + pub(crate) fn namespace(&self, namespace: &str) -> TokenStream { + if self.standalone || namespace == self.namespace { + quote! {} + } else { + let is_external = + namespace.starts_with("Windows.") && !self.namespace.starts_with("Windows"); + let mut relative = self.namespace.split('.').peekable(); + let mut namespace = namespace.split('.').peekable(); + + while relative.peek() == namespace.peek() { + if relative.next().is_none() { + break; + } + + namespace.next(); + } + + let mut tokens = TokenStream::new(); + + if is_external { + tokens.push_str("::windows::"); + namespace.next(); + } else { + for _ in 0..relative.count() { + tokens.push_str("super::"); + } + } + + for namespace in namespace { + tokens.push_str(namespace); + tokens.push_str("::"); + } + + tokens + } + } + pub fn crate_name(&self) -> TokenStream { + if self.standalone { + TokenStream::new() + } else if self.sys { + "::windows_sys::core::".into() + } else { + "::windows::core::".into() + } + } + fn scoped_name(&self, def: TypeDef) -> String { + if let Some(enclosing_type) = self.reader.type_def_enclosing_type(def) { + for (index, nested_type) in self.reader.nested_types(enclosing_type).enumerate() { + if self.reader.type_def_name(nested_type) == self.reader.type_def_name(def) { + return format!("{}_{index}", &self.scoped_name(enclosing_type)); + } + } + } + self.reader.type_def_name(def).to_string() + } + pub fn value(&self, value: &Value) -> TokenStream { + match value { + Value::Bool(value) => quote! { #value }, + Value::U8(value) => quote! { #value }, + Value::I8(value) => quote! { #value }, + Value::U16(value) => quote! { #value }, + Value::I16(value) => quote! { #value }, + Value::U32(value) => quote! { #value }, + Value::I32(value) => quote! { #value }, + Value::U64(value) => quote! { #value }, + Value::I64(value) => quote! { #value }, + Value::F32(value) => quote! { #value }, + Value::F64(value) => quote! { #value }, + Value::String(value) => { + let mut tokens = "\"".to_string(); + + for u in value.chars() { + write!(tokens, "{}", u.escape_default()).unwrap(); + } + + tokens.push('\"'); + tokens.into() + } + _ => unimplemented!(), + } + } + pub fn typed_value(&self, value: &Value) -> TokenStream { + let literal = self.value(value); + match value { + Value::Bool(_) => quote! { bool = #literal }, + Value::U8(_) => quote! { u8 = #literal }, + Value::I8(_) => quote! { i8 = #literal }, + Value::U16(_) => quote! { u16 = #literal }, + Value::I16(_) => quote! { i16 = #literal }, + Value::U32(_) => quote! { u32 = #literal }, + Value::I32(_) => quote! { i32 = #literal }, + Value::U64(_) => quote! { u64 = #literal }, + Value::I64(_) => quote! { i64 = #literal }, + Value::F32(_) => quote! { f32 = #literal }, + Value::F64(_) => quote! { f64 = #literal }, + Value::String(_) => { + quote! { &str = #literal } + } + _ => unimplemented!(), + } + } + + pub fn guid(&self, value: &GUID) -> TokenStream { + let guid = self.type_name(&Type::GUID); + format!("{}::from_u128(0x{:08x?}_{:04x?}_{:04x?}_{:02x?}{:02x?}_{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?})", guid.into_string(), value.0, value.1, value.2, value.3, value.4, value.5, value.6, value.7, value.8, value.9, value.10).into() + } + pub fn interface_core_traits( + &self, + def: TypeDef, + _generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + let name = trim_tick(self.reader.type_def_name(def)); + quote! { + #features + impl<#constraints> ::core::cmp::PartialEq for #ident { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + #features + impl<#constraints> ::core::cmp::Eq for #ident {} + #features + impl<#constraints> ::core::fmt::Debug for #ident { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple(#name).field(&self.0).finish() + } + } + } + } + pub fn agile( + &self, + def: TypeDef, + ident: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + if self.reader.type_def_is_agile(def) { + quote! { + #features + unsafe impl<#constraints> ::core::marker::Send for #ident {} + #features + unsafe impl<#constraints> ::core::marker::Sync for #ident {} + } + } else { + quote! {} + } + } + pub fn async_get( + &self, + def: TypeDef, + generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + let mut kind = self.reader.type_def_async_kind(def); + let mut async_generics = generics.to_vec(); + + if kind == AsyncKind::None { + for interface in self.reader.type_def_interfaces(def, generics) { + if let Type::TypeDef((interface_def, interface_generics)) = &interface.ty { + kind = self.reader.type_def_async_kind(*interface_def); + if kind != AsyncKind::None { + async_generics = interface_generics.to_vec(); + break; + } + } + } + } + + if kind == AsyncKind::None { + quote! {} + } else { + let return_type = match kind { + AsyncKind::Operation | AsyncKind::OperationWithProgress => { + self.type_name(&async_generics[0]) + } + _ => quote! { () }, + }; + + let handler = match kind { + AsyncKind::Action => quote! { AsyncActionCompletedHandler }, + AsyncKind::ActionWithProgress => quote! { AsyncActionWithProgressCompletedHandler }, + AsyncKind::Operation => quote! { AsyncOperationCompletedHandler }, + AsyncKind::OperationWithProgress => { + quote! { AsyncOperationWithProgressCompletedHandler } + } + _ => unimplemented!(), + }; + + let namespace = self.namespace("Windows.Foundation"); + + quote! { + #features + impl<#constraints> #ident { + pub fn get(&self) -> ::windows::core::Result<#return_type> { + if self.Status()? == #namespace AsyncStatus::Started { + 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(); } + Ok(()) + }))?; + } + self.GetResults() + } + } + #features + impl<#constraints> ::std::future::Future for #ident { + type Output = ::windows::core::Result<#return_type>; + + fn poll(self: ::std::pin::Pin<&mut Self>, context: &mut ::std::task::Context) -> ::std::task::Poll<Self::Output> { + if self.Status()? == #namespace AsyncStatus::Started { + let waker = context.waker().clone(); + + let _ = self.SetCompleted(&#namespace #handler::new(move |_sender, _args| { + waker.wake_by_ref(); + Ok(()) + })); + + ::std::task::Poll::Pending + } else { + ::std::task::Poll::Ready(self.GetResults()) + } + } + } + } + } + } + pub fn interface_winrt_trait( + &self, + def: TypeDef, + generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + if self + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + 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::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::imp::ConstBuffer::from_slice(#signature) } + } else { + let generics = generics.iter().enumerate().map(|(index, g)| { + let g = self.type_name(g); + let semi = if index != generics.len() - 1 { + Some(quote! { + .push_slice(b";") + }) + } else { + None + }; + + quote! { + .push_other(<#g as ::windows::core::RuntimeType>::SIGNATURE) + #semi + } + }); + + quote! { + { + ::windows::imp::ConstBuffer::new() + .push_slice(b"pinterface(") + .push_slice(#signature) + .push_slice(b";") + #(#generics)* + .push_slice(b")") + } + } + } + }; + + quote! { + #features + impl<#constraints> ::windows::core::RuntimeType for #ident { + const SIGNATURE: ::windows::imp::ConstBuffer = #type_signature; + } + } + } else { + quote! {} + } + } + pub fn runtime_name_trait( + &self, + def: TypeDef, + _generics: &[Type], + name: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + if self + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + // TODO: this needs to use a ConstBuffer-like facility to accomodate generics + let runtime_name = format!("{}", self.reader.type_def_type_name(def)); + + quote! { + #features + impl<#constraints> ::windows::core::RuntimeName for #name { + const NAME: &'static str = #runtime_name; + } + } + } else { + quote! { + #features + impl ::windows::core::RuntimeName for #name {} + } + } + } + + pub fn interface_trait( + &self, + def: TypeDef, + generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + has_unknown_base: bool, + ) -> TokenStream { + if let Some(default) = self.reader.type_def_default_interface(def) { + let default_name = self.type_name(&default); + let vtbl = self.type_vtbl_name(&default); + quote! { + #features + impl<#constraints> ::core::clone::Clone for #ident { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + #features + unsafe impl ::windows::core::Interface for #ident { + type Vtable = #vtbl; + } + #features + unsafe impl ::windows::core::ComInterface for #ident { + const IID: ::windows::core::GUID = <#default_name as ::windows::core::ComInterface>::IID; + } + } + } else { + let vtbl = self.type_def_vtbl_name(def, generics); + let guid = if generics.is_empty() { + match self.reader.type_def_guid(def) { + Some(guid) => self.guid(&guid), + None => { + quote! { + ::windows::core::GUID::zeroed() + } + } + } + } else { + quote! { + ::windows::core::GUID::from_signature(<Self as ::windows::core::RuntimeType>::SIGNATURE) + } + }; + + let phantoms = self.generic_phantoms(generics); + + let mut tokens = quote! { + #features + unsafe impl<#constraints> ::windows::core::Interface for #ident { + type Vtable = #vtbl; + } + #features + impl<#constraints> ::core::clone::Clone for #ident { + fn clone(&self) -> Self { + Self(self.0.clone(), #phantoms) + } + } + }; + + if has_unknown_base { + tokens.combine("e! { + #features + unsafe impl<#constraints> ::windows::core::ComInterface for #ident { + const IID: ::windows::core::GUID = #guid; + } + }); + } + + tokens + } + } + pub fn interface_vtbl( + &self, + def: TypeDef, + generics: &[Type], + _ident: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + let vtbl = self.type_def_vtbl_name(def, generics); + let mut methods = quote! {}; + let mut method_names = MethodNames::new(); + method_names.add_vtable_types(self, def); + let phantoms = self.generic_named_phantoms(generics); + + match self.reader.type_def_vtables(def).last() { + Some(Type::IUnknown) => { + methods.combine("e! { pub base__: ::windows::core::IUnknown_Vtbl, }) + } + Some(Type::IInspectable) => { + methods.combine("e! { pub base__: ::windows::core::IInspectable_Vtbl, }) + } + Some(Type::TypeDef((def, _))) => { + let vtbl = self.type_def_vtbl_name(*def, &[]); + methods.combine("e! { pub base__: #vtbl, }); + } + _ => {} + } + + for method in self.reader.type_def_methods(def) { + if self.reader.method_def_name(method) == ".ctor" { + continue; + } + let name = method_names.add(self, method); + let signature = self.reader.method_def_signature(method, generics); + let mut cfg = self.reader.signature_cfg(&signature); + let signature = self.vtbl_signature(def, generics, &signature); + cfg.add_feature(self.reader.type_def_namespace(def)); + let cfg_all = self.cfg_features(&cfg); + let cfg_not = self.cfg_not_features(&cfg); + + let signature = quote! { pub #name: unsafe extern "system" fn #signature, }; + + if cfg_all.is_empty() { + methods.combine(&signature); + } else { + methods.combine("e! { + #cfg_all + #signature + #cfg_not + #name: usize, + }); + } + } + + quote! { + #features + #[repr(C)] #[doc(hidden)] pub struct #vtbl where #constraints { + #methods + #(pub #phantoms)* + } + } + } + pub fn vtbl_signature( + &self, + def: TypeDef, + _generics: &[Type], + signature: &Signature, + ) -> TokenStream { + let is_winrt = self + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT); + let hresult = self.type_name(&Type::HRESULT); + + let (trailing_return_type, return_type, udt_return_type) = if is_winrt { + if let Some(return_type) = &signature.return_type { + if let Type::WinrtArray(kind) = return_type { + let tokens = self.type_abi_name(kind); + ( + quote! { result_size__: *mut u32, result__: *mut *mut #tokens }, + quote! { -> #hresult }, + quote! {}, + ) + } else { + let tokens = self.type_abi_name(return_type); + ( + quote! { result__: *mut #tokens }, + quote! { -> #hresult }, + quote! {}, + ) + } + } else { + (quote! {}, quote! { -> #hresult }, quote! {}) + } + } else if let Some(return_type) = &signature.return_type { + if self.reader.type_is_struct(return_type) { + let tokens = self.type_abi_name(return_type); + (quote! {}, quote! {}, quote! { result__: *mut #tokens, }) + } else { + let tokens = self.type_default_name(return_type); + (quote! {}, quote! { -> #tokens }, quote! {}) + } + } else { + (quote! {}, quote! {}, quote! {}) + }; + + let params = signature.params.iter().map(|p| { + let name = self.param_name(p.def); + if is_winrt { + let abi = self.type_abi_name(&p.ty); + let abi_size_name: TokenStream = + format!("{}_array_size", self.reader.param_name(p.def)).into(); + + if self + .reader + .param_flags(p.def) + .contains(ParamAttributes::INPUT) + { + if p.ty.is_winrt_array() { + quote! { #abi_size_name: u32, #name: *const #abi, } + } else if p.ty.is_winrt_const_ref() { + quote! { #name: &#abi, } + } else { + quote! { #name: #abi, } + } + } else if p.ty.is_winrt_array() { + quote! { #abi_size_name: u32, #name: *mut #abi, } + } else if p.ty.is_winrt_array_ref() { + quote! { #abi_size_name: *mut u32, #name: *mut *mut #abi, } + } else { + quote! { #name: *mut #abi, } + } + } else { + match p.kind { + SignatureParamKind::ValueType => { + let abi = self.type_default_name(&p.ty); + quote! { #name: #abi, } + } + _ => { + let abi = self.type_abi_name(&p.ty); + quote! { #name: #abi, } + } + } + } + }); + + quote! { (this: *mut ::core::ffi::c_void, #udt_return_type #(#params)* #trailing_return_type) #return_type } + } + pub fn param_name(&self, param: Param) -> TokenStream { + // In Rust, function parameters cannot be named the same as structs. This avoids some collisions that occur in the win32 metadata. + // See Icmp6SendEcho2 for an example. + to_ident(&self.reader.param_name(param).to_lowercase()) + } + pub fn return_sig(&self, signature: &Signature) -> TokenStream { + if let Some(return_type) = &signature.return_type { + let tokens = self.type_default_name(return_type); + format!(" -> {}", tokens.as_str()).into() + } else if self.reader.method_def_does_not_return(signature.def) { + " -> !".into() + } else { + " -> ()".into() + } + } + pub fn win32_args(&self, params: &[SignatureParam], kind: SignatureKind) -> TokenStream { + let mut tokens = quote! {}; + + for (position, param) in params.iter().enumerate() { + let new = match kind { + SignatureKind::Query(query) if query.object == position => { + quote! { &mut result__, } + } + SignatureKind::ReturnValue | SignatureKind::ResultValue + if params.len() - 1 == position => + { + quote! { &mut result__, } + } + SignatureKind::QueryOptional(query) if query.object == position => { + quote! { result__ as *mut _ as *mut _, } + } + SignatureKind::Query(query) | SignatureKind::QueryOptional(query) + if query.guid == position => + { + quote! { &<T as ::windows::core::ComInterface>::IID, } + } + _ => { + let name = self.param_name(param.def); + let flags = self.reader.param_flags(param.def); + match param.kind { + SignatureParamKind::ArrayFixed(_) + | SignatureParamKind::ArrayRelativeLen(_) + | SignatureParamKind::ArrayRelativeByteLen(_) => { + let map = if flags.contains(ParamAttributes::OPTIONAL) { + quote! { #name.as_deref().map_or(::core::ptr::null(), |slice|slice.as_ptr()) } + } else { + quote! { #name.as_ptr() } + }; + quote! { ::core::mem::transmute(#map), } + } + SignatureParamKind::ArrayRelativePtr(relative) => { + let name = self.param_name(params[relative].def); + let flags = self.reader.param_flags(params[relative].def); + if flags.contains(ParamAttributes::OPTIONAL) { + quote! { #name.as_deref().map_or(0, |slice|slice.len() as _), } + } else { + quote! { #name.len() as _, } + } + } + SignatureParamKind::TryInto => { + quote! { #name.try_into_param()?.abi(), } + } + SignatureParamKind::IntoParam => { + quote! { #name.into_param().abi(), } + } + SignatureParamKind::OptionalPointer => { + if flags.contains(ParamAttributes::OUTPUT) { + quote! { ::core::mem::transmute(#name.unwrap_or(::std::ptr::null_mut())), } + } else { + quote! { ::core::mem::transmute(#name.unwrap_or(::std::ptr::null())), } + } + } + SignatureParamKind::ValueType => { + quote! { #name, } + } + SignatureParamKind::Blittable => { + quote! { ::core::mem::transmute(#name), } + } + SignatureParamKind::Other => { + quote! { ::core::mem::transmute_copy(#name), } + } + } + } + }; + tokens.combine(&new) + } + + tokens + } + pub fn win32_params(&self, params: &[SignatureParam], kind: SignatureKind) -> TokenStream { + let mut tokens = quote! {}; + + let mut generic_params = self.generic_params(params); + for (position, param) in params.iter().enumerate() { + match kind { + SignatureKind::Query(query) | SignatureKind::QueryOptional(query) => { + if query.object == position || query.guid == position { + continue; + } + } + SignatureKind::ReturnValue | SignatureKind::ResultValue + if params.len() - 1 == position => + { + continue; + } + _ => {} + } + + let name = self.param_name(param.def); + + match param.kind { + SignatureParamKind::ArrayFixed(fixed) => { + let ty = param.ty.deref(); + let ty = self.type_default_name(&ty); + let len = Literal::u32_unsuffixed(fixed as _); + let ty = if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OUTPUT) + { + quote! { &mut [#ty; #len] } + } else { + quote! { &[#ty; #len] } + }; + if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OPTIONAL) + { + tokens.combine("e! { #name: ::core::option::Option<#ty>, }); + } else { + tokens.combine("e! { #name: #ty, }); + } + } + SignatureParamKind::ArrayRelativeLen(_) => { + let ty = param.ty.deref(); + let ty = self.type_default_name(&ty); + let ty = if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OUTPUT) + { + quote! { &mut [#ty] } + } else { + quote! { &[#ty] } + }; + if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OPTIONAL) + { + tokens.combine("e! { #name: ::core::option::Option<#ty>, }); + } else { + tokens.combine("e! { #name: #ty, }); + } + } + SignatureParamKind::ArrayRelativeByteLen(_) => { + let ty = if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OUTPUT) + { + quote! { &mut [u8] } + } else { + quote! { &[u8] } + }; + if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OPTIONAL) + { + tokens.combine("e! { #name: ::core::option::Option<#ty>, }); + } else { + tokens.combine("e! { #name: #ty, }); + } + } + SignatureParamKind::ArrayRelativePtr(_) => {} + SignatureParamKind::TryInto | SignatureParamKind::IntoParam => { + let (position, _) = generic_params.next().unwrap(); + let kind: TokenStream = format!("P{position}").into(); + tokens.combine("e! { #name: #kind, }); + } + SignatureParamKind::OptionalPointer => { + let kind = self.type_default_name(¶m.ty); + tokens.combine("e! { #name: ::core::option::Option<#kind>, }); + } + SignatureParamKind::ValueType | SignatureParamKind::Blittable => { + let kind = self.type_default_name(¶m.ty); + tokens.combine("e! { #name: #kind, }); + } + SignatureParamKind::Other => { + let kind = self.type_default_name(¶m.ty); + tokens.combine("e! { #name: &#kind, }); + } + } + } + + tokens + } + + pub fn impl_signature(&self, def: TypeDef, signature: &Signature) -> TokenStream { + if self + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + let is_delegate = self.reader.type_def_kind(def) == TypeKind::Delegate; + let params = signature + .params + .iter() + .map(|p| self.winrt_produce_type(p, !is_delegate)); + + let return_type = if let Some(return_type) = &signature.return_type { + let tokens = self.type_name(return_type); + + if return_type.is_winrt_array() { + quote! { ::windows::core::Array<#tokens> } + } else { + tokens + } + } else { + quote! { () } + }; + + let this = if is_delegate { + quote! {} + } else { + quote! { &self, } + }; + + quote! { (#this #(#params),*) -> ::windows::core::Result<#return_type> } + } else { + let signature_kind = self.reader.signature_kind(signature); + let mut params = quote! {}; + + if signature_kind == SignatureKind::ResultValue { + for param in &signature.params[..signature.params.len() - 1] { + params.combine(&self.win32_produce_type(param)); + } + } else { + for param in &signature.params { + params.combine(&self.win32_produce_type(param)); + } + } + + let return_type = match signature_kind { + SignatureKind::ReturnVoid => quote! {}, + SignatureKind::Query(_) + | SignatureKind::QueryOptional(_) + | SignatureKind::ResultVoid => quote! { -> ::windows::core::Result<()> }, + SignatureKind::ResultValue => { + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let return_type = self.type_name(&return_type); + + quote! { -> ::windows::core::Result<#return_type> } + } + _ => self.return_sig(signature), + }; + + quote! { (&self, #params) #return_type } + } + } + fn winrt_produce_type(&self, param: &SignatureParam, include_param_names: bool) -> TokenStream { + let default_type = self.type_default_name(¶m.ty); + + let sig = if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if param.ty.is_winrt_array() { + quote! { &[#default_type] } + } else if self.reader.type_is_primitive(¶m.ty) { + quote! { #default_type } + } else if self.reader.type_is_nullable(¶m.ty) { + let type_name = self.type_name(¶m.ty); + quote! { ::core::option::Option<&#type_name> } + } else { + quote! { &#default_type } + } + } else if param.ty.is_winrt_array() { + quote! { &mut [#default_type] } + } else if param.ty.is_winrt_array_ref() { + let kind = self.type_name(¶m.ty); + quote! { &mut ::windows::core::Array<#kind> } + } else { + quote! { &mut #default_type } + }; + + if include_param_names { + let name = self.param_name(param.def); + quote! { #name: #sig } + } else { + sig + } + } + fn win32_produce_type(&self, param: &SignatureParam) -> TokenStream { + let name = self.param_name(param.def); + let kind = self.type_default_name(¶m.ty); + + if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if self.reader.type_is_primitive(¶m.ty) { + quote! { #name: #kind, } + } else if self.reader.type_is_nullable(¶m.ty) { + let kind = self.type_name(¶m.ty); + quote! { #name: ::core::option::Option<&#kind>, } + } else { + quote! { #name: &#kind, } + } + } else { + quote! { #name: #kind, } + } + } +} + +pub fn to_ident(name: &str) -> TokenStream { + // keywords list based on https://doc.rust-lang.org/reference/keywords.html + match name { + "abstract" | "as" | "become" | "box" | "break" | "const" | "continue" | "crate" | "do" + | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in" + | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | "override" | "priv" + | "pub" | "ref" | "return" | "static" | "struct" | "super" | "trait" | "true" | "type" + | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | "while" | "yield" + | "try" | "async" | "await" | "dyn" => format!("r#{name}").into(), + "Self" | "self" => format!("{name}_").into(), + "_" => "unused".into(), + _ => trim_tick(name).into(), + } +} + +fn mut_ptrs(pointers: usize) -> TokenStream { + "*mut ".repeat(pointers).into() +} + +fn const_ptrs(pointers: usize) -> TokenStream { + "*const ".repeat(pointers).into() +} + +fn to_feature(name: &str) -> String { + let mut feature = String::new(); + + for name in name.split('.').skip(1) { + feature.push_str(name); + feature.push('_'); + } + + if feature.is_empty() { + feature = name.to_string(); + } else { + feature.truncate(feature.len() - 1); + } + + feature +} + +fn starts_with(namespace: &str, feature: &str) -> bool { + if namespace == feature { + return true; + } + + if namespace.len() > feature.len() && namespace.as_bytes().get(feature.len()) == Some(&b'.') { + return namespace.starts_with(feature); + } + + false +} + +fn gen_mut_ptrs(pointers: usize) -> TokenStream { + "*mut ".repeat(pointers).into() +} + +fn gen_const_ptrs(pointers: usize) -> TokenStream { + "*const ".repeat(pointers).into() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_starts_with() { + assert!(starts_with( + "Windows.Win32.Graphics.Direct3D11on12", + "Windows.Win32.Graphics.Direct3D11on12" + )); + assert!(starts_with( + "Windows.Win32.Graphics.Direct3D11on12", + "Windows.Win32.Graphics" + )); + assert!(!starts_with( + "Windows.Win32.Graphics.Direct3D11on12", + "Windows.Win32.Graphics.Direct3D11" + )); + assert!(!starts_with( + "Windows.Win32.Graphics.Direct3D", + "Windows.Win32.Graphics.Direct3D11" + )); + } +} diff --git a/vendor/windows-bindgen/src/handles.rs b/vendor/windows-bindgen/src/handles.rs new file mode 100644 index 000000000..9ace4a1b6 --- /dev/null +++ b/vendor/windows-bindgen/src/handles.rs @@ -0,0 +1,109 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.sys { + gen_sys_handle(gen, def) + } else { + gen_win_handle(gen, def) + } +} + +pub fn gen_sys_handle(gen: &Gen, def: TypeDef) -> TokenStream { + let ident = to_ident(gen.reader.type_def_name(def)); + match gen.reader.type_def_underlying_type(def) { + Type::ISize if gen.std => quote! { + pub type #ident = *mut ::core::ffi::c_void; + }, + Type::USize if gen.std => quote! { + #[cfg(target_pointer_width = "32")] + pub type #ident = u32; + #[cfg(target_pointer_width = "64")] + pub type #ident = u64; + }, + underlying_type => { + let signature = gen.type_default_name(&underlying_type); + + quote! { + pub type #ident = #signature; + } + } + } +} + +pub fn gen_win_handle(gen: &Gen, def: TypeDef) -> TokenStream { + let name = gen.reader.type_def_name(def); + let ident = to_ident(name); + let underlying_type = gen.reader.type_def_underlying_type(def); + let signature = gen.type_default_name(&underlying_type); + let check = if underlying_type.is_pointer() { + quote! { + impl #ident { + pub fn is_invalid(&self) -> bool { + self.0.is_null() + } + } + } + } else { + let invalid = gen.reader.type_def_invalid_values(def); + + if !invalid.is_empty() { + let invalid = invalid.iter().map(|value| { + let literal = Literal::i64_unsuffixed(*value); + + if *value < 0 && underlying_type.is_unsigned() { + quote! { self.0 == #literal as _ } + } else { + quote! { self.0 == #literal } + } + }); + quote! { + impl #ident { + pub fn is_invalid(&self) -> bool { + #(#invalid)||* + } + } + } + } else { + quote! {} + } + }; + + let mut tokens = quote! { + #[repr(transparent)] + // Unfortunately, Rust requires these to be derived to allow constant patterns. + #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] + pub struct #ident(pub #signature); + #check + impl ::core::default::Default for #ident { + fn default() -> Self { + unsafe { ::core::mem::zeroed() } + } + } + impl ::core::clone::Clone for #ident { + fn clone(&self) -> Self { + *self + } + } + impl ::core::marker::Copy for #ident {} + impl ::core::fmt::Debug for #ident { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple(#name).field(&self.0).finish() + } + } + impl ::windows::core::TypeKind for #ident { + type TypeKind = ::windows::core::CopyType; + } + }; + + if let Some(dependency) = gen.reader.type_def_usable_for(def) { + let type_name = gen.reader.type_def_type_name(dependency); + let mut dependency = gen.namespace(type_name.namespace); + dependency.push_str(type_name.name); + + tokens.combine("e! { + impl windows::core::CanInto<#dependency> for #ident {} + }); + } + + tokens +} diff --git a/vendor/windows-bindgen/src/implements.rs b/vendor/windows-bindgen/src/implements.rs new file mode 100644 index 000000000..3a3184b51 --- /dev/null +++ b/vendor/windows-bindgen/src/implements.rs @@ -0,0 +1,191 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.reader.type_def_kind(def) != TypeKind::Interface + || (!gen.component && !gen.reader.type_def_can_implement(def)) + { + return quote! {}; + } + + let generics: &Vec<Type> = &gen.reader.type_def_generics(def).collect(); + let type_ident = to_ident(gen.reader.type_def_name(def)); + let impl_ident = type_ident.join("_Impl"); + let vtbl_ident = type_ident.join("_Vtbl"); + let implvtbl_ident = impl_ident.join("Vtbl"); + let constraints = gen.generic_constraints(generics); + let generic_names = gen.generic_names(generics); + let named_phantoms = gen.generic_named_phantoms(generics); + let cfg = gen.reader.type_def_cfg_impl(def, generics); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + let mut requires = quote! {}; + let type_ident = quote! { #type_ident<#generic_names> }; + let vtables = gen.reader.type_def_vtables(def); + let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown)); + + fn gen_required_trait(gen: &Gen, def: TypeDef, generics: &[Type]) -> TokenStream { + let name = gen.type_def_name_imp(def, generics, "_Impl"); + quote! { + + #name + } + } + + let mut matches = quote! { iid == &<#type_ident as ::windows::core::ComInterface>::IID }; + + if let Some(Type::TypeDef((def, _))) = vtables.last() { + requires.combine(&gen_required_trait(gen, *def, &[])) + } + + for def in &vtables { + if let Type::TypeDef((def, generics)) = def { + let name = gen.type_def_name(*def, generics); + + matches.combine("e! { + || iid == &<#name as ::windows::core::ComInterface>::IID + }) + } + } + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + // TODO: this awkward wrapping of TypeDefs needs fixing + for interface in gen + .reader + .type_interfaces(&Type::TypeDef((def, generics.to_vec()))) + { + if let Type::TypeDef((def, generics)) = interface.ty { + requires.combine(&gen_required_trait(gen, def, &generics)); + } + } + } + + let runtime_name = gen.runtime_name_trait(def, generics, &type_ident, &constraints, &features); + + let mut method_names = MethodNames::new(); + method_names.add_vtable_types(gen, def); + + let method_traits = gen.reader.type_def_methods(def).map(|method| { + let name = method_names.add(gen, method); + let signature = gen.reader.method_def_signature(method, generics); + let signature_tokens = gen.impl_signature(def, &signature); + quote! { fn #name #signature_tokens; } + }); + + let mut method_names = MethodNames::new(); + method_names.add_vtable_types(gen, def); + + let method_impls = gen.reader.type_def_methods(def).map(|method| { + let name = method_names.add(gen, method); + let signature = gen.reader.method_def_signature(method, generics); + let vtbl_signature = gen.vtbl_signature(def, generics, &signature); + + let invoke_upcall = if gen.reader.type_def_flags(def).contains(TypeAttributes::WINRT) { winrt_methods::gen_upcall(gen, &signature, quote! { this.#name }) } else { com_methods::gen_upcall(gen, &signature, quote! { this.#name }) }; + + if has_unknown_base { + quote! { + unsafe extern "system" fn #name<#constraints Identity: ::windows::core::IUnknownImpl<Impl = Impl>, Impl: #impl_ident<#generic_names>, const OFFSET: isize> #vtbl_signature { + // offset the `this` pointer by `OFFSET` times the size of a pointer and cast it as an IUnknown implementation + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + #invoke_upcall + } + } + } else { + quote! { + unsafe extern "system" fn #name<Impl: #impl_ident> #vtbl_signature { + let this = (this as *mut *mut ::core::ffi::c_void) as *const ::windows::core::ScopedHeap; + let this = &*((*this).this as *const Impl); + #invoke_upcall + } + } + } + }); + + let mut methods = quote! {}; + + match vtables.last() { + Some(Type::IUnknown) => methods.combine("e! { base__: ::windows::core::IUnknown_Vtbl::new::<Identity, OFFSET>(), }), + Some(Type::IInspectable) => methods.combine("e! { base__: ::windows::core::IInspectable_Vtbl::new::<Identity, #type_ident, OFFSET>(), }), + Some(Type::TypeDef((def, generics))) => { + let name = gen.type_def_name_imp(*def, generics, "_Vtbl"); + if has_unknown_base { + methods.combine("e! { base__: #name::new::<Identity, Impl, OFFSET>(), }); + } else { + methods.combine("e! { base__: #name::new::<Impl>(), }); + } + } + _ => {} + } + + let mut method_names = MethodNames::new(); + method_names.add_vtable_types(gen, def); + + for method in gen.reader.type_def_methods(def) { + let name = method_names.add(gen, method); + if has_unknown_base { + methods.combine("e! { #name: #name::<#generic_names Identity, Impl, OFFSET>, }); + } else { + methods.combine("e! { #name: #name::<Impl>, }); + } + } + + if has_unknown_base { + quote! { + #doc + #features + pub trait #impl_ident<#generic_names> : Sized #requires where #constraints { + #(#method_traits)* + } + #runtime_name + #features + impl<#constraints> #vtbl_ident<#generic_names> { + pub const fn new<Identity: ::windows::core::IUnknownImpl<Impl = Impl>, Impl: #impl_ident<#generic_names>, const OFFSET: isize>() -> #vtbl_ident<#generic_names> { + #(#method_impls)* + Self{ + #methods + #(#named_phantoms)* + } + } + pub fn matches(iid: &windows::core::GUID) -> bool { + #matches + } + } + } + } else { + quote! { + #doc + #features + pub trait #impl_ident : Sized #requires { + #(#method_traits)* + } + #features + impl #vtbl_ident { + pub const fn new<Impl: #impl_ident>() -> #vtbl_ident { + #(#method_impls)* + Self{ + #methods + #(#named_phantoms)* + } + } + } + #[doc(hidden)] + #features + struct #implvtbl_ident<T: #impl_ident> (::std::marker::PhantomData<T>); + #features + impl<T: #impl_ident> #implvtbl_ident<T> { + const VTABLE: #vtbl_ident = #vtbl_ident::new::<T>(); + } + #features + impl #type_ident { + pub fn new<'a, T: #impl_ident>(this: &'a T) -> ::windows::core::ScopedInterface<'a, Self> { + let this = ::windows::core::ScopedHeap { vtable: &#implvtbl_ident::<T>::VTABLE as *const _ as *const _, this: this as *const _ as *const _ }; + let this = ::std::mem::ManuallyDrop::new(::std::boxed::Box::new(this)); + unsafe { ::windows::core::ScopedInterface::new(::std::mem::transmute(&this.vtable)) } + } + } + } + } +} diff --git a/vendor/windows-bindgen/src/interfaces.rs b/vendor/windows-bindgen/src/interfaces.rs new file mode 100644 index 000000000..1643e7798 --- /dev/null +++ b/vendor/windows-bindgen/src/interfaces.rs @@ -0,0 +1,224 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.sys { + gen_sys_interface(gen, def) + } else { + gen_win_interface(gen, def) + } +} + +fn gen_sys_interface(gen: &Gen, def: TypeDef) -> TokenStream { + let name = gen.reader.type_def_name(def); + let ident = to_ident(name); + + if gen.reader.type_def_is_exclusive(def) { + quote! {} + } else { + quote! { + pub type #ident = *mut ::core::ffi::c_void; + } + } +} + +fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { + let generics: &Vec<Type> = &gen.reader.type_def_generics(def).collect(); + let ident = gen.type_def_name(def, generics); + let is_exclusive = gen.reader.type_def_is_exclusive(def); + let phantoms = gen.generic_phantoms(generics); + let constraints = gen.generic_constraints(generics); + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + let interfaces = gen + .reader + .type_interfaces(&Type::TypeDef((def, generics.to_vec()))); + let vtables = gen.reader.type_def_vtables(def); + let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown)); + + let mut tokens = if is_exclusive { + quote! { #[doc(hidden)] } + } else { + quote! { #doc } + }; + + if has_unknown_base { + tokens.combine("e! { + #features + #[repr(transparent)] + pub struct #ident(::windows::core::IUnknown, #phantoms) where #constraints; + }); + } else { + tokens.combine("e! { + #features + #[repr(transparent)] + pub struct #ident(::std::ptr::NonNull<::std::ffi::c_void>); + }); + } + + if !is_exclusive { + let mut methods = quote! {}; + // We need to distinguish between public and virtual methods because some WinRT type hierarchies inherit colliding (overloaded) + // methods that must be distinguishable. + let method_names = &mut MethodNames::new(); + let virtual_names = &mut MethodNames::new(); + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + for method in gen.reader.type_def_methods(def) { + methods.combine(&winrt_methods::gen( + gen, + def, + generics, + InterfaceKind::Default, + method, + method_names, + virtual_names, + )); + } + for interface in &interfaces { + if let Type::TypeDef((def, generics)) = &interface.ty { + for method in gen.reader.type_def_methods(*def) { + methods.combine(&winrt_methods::gen( + gen, + *def, + generics, + InterfaceKind::None, + method, + method_names, + virtual_names, + )); + } + } + } + } else { + let mut bases = vtables.len(); + for ty in &vtables { + match ty { + Type::IUnknown | Type::IInspectable => {} + Type::TypeDef((def, _)) => { + let kind = if gen.reader.type_def_type_name(*def) == TypeName::IDispatch { + InterfaceKind::None + } else { + InterfaceKind::Default + }; + for method in gen.reader.type_def_methods(*def) { + methods.combine(&com_methods::gen( + gen, + *def, + kind, + method, + method_names, + virtual_names, + bases, + )); + } + } + _ => unimplemented!(), + } + + bases -= 1; + } + for method in gen.reader.type_def_methods(def) { + methods.combine(&com_methods::gen( + gen, + def, + InterfaceKind::Default, + method, + method_names, + virtual_names, + 0, + )); + } + } + + tokens.combine("e! { + #features + impl<#constraints> #ident { + #methods + } + }); + + if !vtables.is_empty() && generics.is_empty() { + let mut hierarchy = format!("::windows::imp::interface_hierarchy!({ident}"); + let mut hierarchy_cfg = cfg.clone(); + + for ty in &vtables { + let into = gen.type_name(ty); + + write!(&mut hierarchy, ", {into}").unwrap(); + hierarchy_cfg = hierarchy_cfg.union(&gen.reader.type_cfg(ty)); + } + + hierarchy.push_str(");"); + tokens.combine(&gen.cfg_features(&hierarchy_cfg)); + tokens.push_str(&hierarchy); + } else { + for ty in &vtables { + let into = gen.type_name(ty); + let cfg = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(ty))); + tokens.combine("e! { + #cfg + impl<#constraints> windows::core::CanInto<#into> for #ident {} + }); + } + } + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + for interface in &interfaces { + let into = gen.type_name(&interface.ty); + let cfg = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(&interface.ty))); + tokens.combine("e! { + #cfg + impl<#constraints> windows::core::CanTryInto<#into> for #ident {} + }); + } + } + + tokens.combine(&gen.interface_core_traits( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&gen.interface_winrt_trait( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&gen.async_get(def, generics, &ident, &constraints, &phantoms, &features)); + tokens.combine(&iterators::gen( + gen, + def, + generics, + &ident, + &constraints, + &phantoms, + &cfg, + )); + tokens.combine(&gen.agile(def, &ident, &constraints, &features)); + } + + tokens.combine(&gen.interface_trait( + def, + generics, + &ident, + &constraints, + &features, + has_unknown_base, + )); + tokens.combine(&gen.interface_vtbl(def, generics, &ident, &constraints, &features)); + tokens +} diff --git a/vendor/windows-bindgen/src/iterators.rs b/vendor/windows-bindgen/src/iterators.rs new file mode 100644 index 000000000..49a90adf2 --- /dev/null +++ b/vendor/windows-bindgen/src/iterators.rs @@ -0,0 +1,259 @@ +use super::*; + +pub fn gen( + gen: &Gen, + def: TypeDef, + generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + cfg: &Cfg, +) -> TokenStream { + match gen.reader.type_def_type_name(def) { + // If the type is IIterator<T> then simply implement the Iterator trait over top. + TypeName::IIterator => { + return quote! { + impl<T: ::windows::core::RuntimeType> ::core::iter::Iterator for IIterator<T> { + type Item = T; + + fn next(&mut self) -> ::core::option::Option<Self::Item> { + let result = self.Current().ok(); + + if result.is_some() { + self.MoveNext().ok()?; + } + + result + } + } + }; + } + // If the type is IIterable<T> then implement the IntoIterator trait and rely on the resulting + // IIterator<T> returned by first() to implement the Iterator trait. + TypeName::IIterable => { + return quote! { + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for IIterable<T> { + type Item = T; + type IntoIter = IIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for &IIterable<T> { + type Item = T; + type IntoIter = IIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + // TODO: not sure how to avoid this unwrap, although it should always succeed in practice. + self.First().unwrap() + } + } + }; + } + // If the type is IVectorView<T> then provide the VectorViewIterator fast iterator. + TypeName::IVectorView => { + return quote! { + pub struct VectorViewIterator<T: ::windows::core::RuntimeType + 'static> { + vector: ::core::option::Option<IVectorView<T>>, + current: u32, + } + + impl<T: ::windows::core::RuntimeType> VectorViewIterator<T> { + pub fn new(vector: ::core::option::Option<IVectorView<T>>) -> Self { + Self { vector, current: 0 } + } + } + + impl<T: ::windows::core::RuntimeType> ::core::iter::Iterator for VectorViewIterator<T> { + type Item = T; + + fn next(&mut self) -> ::core::option::Option<Self::Item> { + self.vector.as_ref() + .and_then(|vector| { + vector.GetAt(self.current).ok() + }) + .and_then(|result| { + self.current += 1; + Some(result) + }) + } + } + + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for IVectorView<T> { + type Item = T; + type IntoIter = VectorViewIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for &IVectorView<T> { + type Item = T; + type IntoIter = VectorViewIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + // TODO: shouldn't need to clone - VectorViewIterator should hold a reference + VectorViewIterator::new(::core::option::Option::Some(::core::clone::Clone::clone(self))) + } + } + }; + } + TypeName::IVector => { + return quote! { + pub struct VectorIterator<T: ::windows::core::RuntimeType + 'static> { + vector: ::core::option::Option<IVector<T>>, + current: u32, + } + + impl<T: ::windows::core::RuntimeType> VectorIterator<T> { + pub fn new(vector: ::core::option::Option<IVector<T>>) -> Self { + Self { vector, current: 0 } + } + } + + impl<T: ::windows::core::RuntimeType> ::core::iter::Iterator for VectorIterator<T> { + type Item = T; + + fn next(&mut self) -> ::core::option::Option<Self::Item> { + self.vector.as_ref() + .and_then(|vector| { + vector.GetAt(self.current).ok() + }) + .and_then(|result| { + self.current += 1; + Some(result) + }) + } + } + + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for IVector<T> { + type Item = T; + type IntoIter = VectorIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for &IVector<T> { + type Item = T; + type IntoIter = VectorIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + // TODO: shouldn't need to clone - VectorIterator should hold a reference + VectorIterator::new(::core::option::Option::Some(::core::clone::Clone::clone(self))) + } + } + }; + } + _ => {} + } + + let wfc = gen.namespace("Windows.Foundation.Collections"); + let mut iterable = None; + let interfaces = gen + .reader + .type_interfaces(&Type::TypeDef((def, generics.to_vec()))); + + // If the class or interface is not one of the well-known collection interfaces, we then see whether it + // implements any one of them. Here is where we favor IVectorView/IVector over IIterable. + for interface in interfaces { + if let Type::TypeDef((interface, interface_generics)) = &interface.ty { + match gen.reader.type_def_type_name(*interface) { + TypeName::IVectorView => { + let item = gen.type_name(&interface_generics[0]); + let mut cfg = cfg.clone(); + gen.reader + .type_def_cfg_combine(*interface, interface_generics, &mut cfg); + let features = gen.cfg_features(&cfg); + + return quote! { + #features + impl<#constraints> ::core::iter::IntoIterator for #ident { + type Item = #item; + type IntoIter = #wfc VectorViewIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + #features + impl<#constraints> ::core::iter::IntoIterator for &#ident { + type Item = #item; + type IntoIter = #wfc VectorViewIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + #wfc VectorViewIterator::new(::windows::core::ComInterface::cast(self).ok()) + } + } + }; + } + TypeName::IVector => { + let item = gen.type_name(&interface_generics[0]); + let mut cfg = cfg.clone(); + gen.reader + .type_def_cfg_combine(*interface, interface_generics, &mut cfg); + let features = gen.cfg_features(&cfg); + + return quote! { + #features + impl<#constraints> ::core::iter::IntoIterator for #ident { + type Item = #item; + type IntoIter = #wfc VectorIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + #features + impl<#constraints> ::core::iter::IntoIterator for &#ident { + type Item = #item; + type IntoIter = #wfc VectorIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + #wfc VectorIterator::new(::windows::core::ComInterface::cast(self).ok()) + } + } + }; + } + TypeName::IIterable => { + iterable = Some((*interface, interface_generics.to_vec())); + } + _ => {} + } + } + } + + match iterable { + None => TokenStream::new(), + Some((interface, interface_generics)) => { + let item = gen.type_name(&interface_generics[0]); + let mut cfg = cfg.clone(); + gen.reader + .type_def_cfg_combine(interface, &interface_generics, &mut cfg); + let features = gen.cfg_features(&cfg); + + quote! { + #features + impl<#constraints> ::core::iter::IntoIterator for #ident { + type Item = #item; + type IntoIter = #wfc IIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + #features + impl<#constraints> ::core::iter::IntoIterator for &#ident { + type Item = #item; + type IntoIter = #wfc IIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + // TODO: not sure how to avoid this unwrap, although it should always succeed in practice. + self.First().unwrap() + } + } + } + } + } +} diff --git a/vendor/windows-bindgen/src/lib.rs b/vendor/windows-bindgen/src/lib.rs new file mode 100644 index 000000000..0957a4f64 --- /dev/null +++ b/vendor/windows-bindgen/src/lib.rs @@ -0,0 +1,225 @@ +/*! +Learn more about Rust for Windows here: <https://github.com/microsoft/windows-rs> +*/ + +mod classes; +mod com_methods; +mod constants; +mod delegates; +mod enums; +mod extensions; +mod functions; +mod gen; +mod handles; +mod implements; +mod interfaces; +mod iterators; +mod method_names; +mod standalone; +mod structs; +mod try_format; +mod winrt_methods; + +use metadata::reader::*; +use method_names::*; +pub use standalone::*; +use std::collections::*; +use std::fmt::Write; +use tokens::*; +use try_format::*; + +#[doc(hidden)] +pub use gen::*; + +#[doc(hidden)] +pub fn namespace(gen: &Gen, tree: &Tree) -> String { + let mut tokens = TokenStream::new(); + + if tree.namespace == "Windows" || !tree.namespace.starts_with("Windows.") { + tokens.combine(&allow()); + } + + for (name, tree) in &tree.nested { + let name = to_ident(name); + let namespace = tree.namespace[tree.namespace.find('.').unwrap() + 1..].replace('.', "_"); + if !gen.component { + tokens.combine("e! { #[cfg(feature = #namespace)] }); + } + tokens.combine("e! { pub mod #name; }); + } + + let mut functions = BTreeMap::<&str, TokenStream>::new(); + let mut types = BTreeMap::<TypeKind, BTreeMap<&str, TokenStream>>::new(); + + for method in gen.reader.namespace_functions(tree.namespace) { + let name = gen.reader.method_def_name(method); + functions + .entry(name) + .or_default() + .combine(&functions::gen(gen, method)); + } + + for field in gen.reader.namespace_constants(tree.namespace) { + let name = gen.reader.field_name(field); + types + .entry(TypeKind::Class) + .or_default() + .entry(name) + .or_default() + .combine(&constants::gen(gen, field)); + } + + for def in gen + .reader + .namespace_types(tree.namespace, &Default::default()) + { + let type_name = gen.reader.type_def_type_name(def); + if REMAP_TYPES.iter().any(|(x, _)| x == &type_name) { + continue; + } + if CORE_TYPES.iter().any(|(x, _)| x == &type_name) { + continue; + } + let name = type_name.name; + let kind = gen.reader.type_def_kind(def); + match kind { + TypeKind::Class => { + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + types + .entry(kind) + .or_default() + .insert(name, classes::gen(gen, def)); + } + } + TypeKind::Interface => types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&interfaces::gen(gen, def)), + TypeKind::Enum => types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&enums::gen(gen, def)), + TypeKind::Struct => { + if gen.reader.type_def_fields(def).next().is_none() { + if let Some(guid) = gen.reader.type_def_guid(def) { + let ident = to_ident(name); + let value = gen.guid(&guid); + let guid = gen.type_name(&Type::GUID); + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let constant = quote! { + #doc + pub const #ident: #guid = #value; + }; + types + .entry(TypeKind::Class) + .or_default() + .entry(name) + .or_default() + .combine(&constant); + continue; + } + } + types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&structs::gen(gen, def)); + } + TypeKind::Delegate => types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&delegates::gen(gen, def)), + } + } + + for function in functions.values() { + tokens.combine(function); + } + + for ty in types.values().flat_map(|v| v.values()) { + tokens.combine(ty); + } + + tokens.combine(&extensions::gen_mod(gen, tree.namespace)); + try_format(tokens.into_string()) +} + +#[doc(hidden)] +pub fn namespace_impl(gen: &Gen, tree: &Tree) -> String { + let mut types = BTreeMap::<&str, TokenStream>::new(); + + for def in gen + .reader + .namespace_types(tree.namespace, &Default::default()) + { + let type_name = gen.reader.type_def_type_name(def); + if CORE_TYPES.iter().any(|(x, _)| x == &type_name) { + continue; + } + if gen.reader.type_def_kind(def) != TypeKind::Interface { + continue; + } + let tokens = implements::gen(gen, def); + + if !tokens.is_empty() { + types.insert(type_name.name, tokens); + } + } + + let types = types.values(); + + let mut tokens = quote! { + #(#types)* + }; + + tokens.combine(&extensions::gen_impl(tree.namespace)); + try_format(tokens.into_string()) +} + +/// Generates bindings for a specific component namespace. +pub fn component(namespace: &str, files: &[File]) -> String { + let reader = &Reader::new(files); + let tree = reader.tree(namespace, &Default::default()); + let mut gen = Gen::new(reader); + gen.namespace = tree.namespace; + gen.component = true; + let mut bindings = crate::namespace(&gen, &tree); + bindings.push_str(&namespace_impl(&gen, &tree)); + try_format(bindings) +} + +fn allow() -> TokenStream { + quote! { + #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] + } +} + +/// Expand a possibly empty generics list with a new generic +fn expand_generics(generics: TokenStream, new: TokenStream) -> TokenStream { + if generics.is_empty() { + quote!(#new) + } else { + quote!(#generics, #new) + } +} + +/// Expand a possibly emppty where clause with a new generic constraint +fn expand_where_clause(where_clause: TokenStream, generic: TokenStream) -> TokenStream { + if where_clause.is_empty() { + quote!(where #generic) + } else { + quote!(#where_clause #generic) + } +} diff --git a/vendor/windows-bindgen/src/method_names.rs b/vendor/windows-bindgen/src/method_names.rs new file mode 100644 index 000000000..9f5dad1c6 --- /dev/null +++ b/vendor/windows-bindgen/src/method_names.rs @@ -0,0 +1,30 @@ +use super::*; + +pub struct MethodNames(BTreeMap<String, u32>); + +impl MethodNames { + pub fn new() -> Self { + Self(BTreeMap::new()) + } + + pub fn add(&mut self, gen: &Gen, method: MethodDef) -> TokenStream { + let name = gen.reader.method_def_special_name(method); + let overload = self.0.entry(name.to_string()).or_insert(0); + *overload += 1; + if *overload > 1 { + format!("{name}{overload}").into() + } else { + to_ident(&name) + } + } + + pub fn add_vtable_types(&mut self, gen: &Gen, def: TypeDef) { + for def in gen.reader.type_def_vtables(def) { + if let Type::TypeDef((def, _)) = def { + for method in gen.reader.type_def_methods(def) { + self.add(gen, method); + } + } + } + } +} diff --git a/vendor/windows-bindgen/src/standalone.rs b/vendor/windows-bindgen/src/standalone.rs new file mode 100644 index 000000000..e8db2fca7 --- /dev/null +++ b/vendor/windows-bindgen/src/standalone.rs @@ -0,0 +1,266 @@ +use super::*; + +/// Generates standalone Windows bindings. +pub fn standalone(names: &[&str]) -> String { + let files = &File::with_default(&[]).unwrap(); + let reader = &Reader::new(files); + let gen = &mut Gen::new(reader); + standalone_imp(gen, names) +} + +/// Generates standalone Windows bindings for the Rust Standard Library. +pub fn standalone_std(names: &[&str]) -> String { + let files = &File::with_default(&[]).unwrap(); + let reader = &Reader::new(files); + let gen = &mut Gen::new(reader); + gen.std = true; + standalone_imp(gen, names) +} + +fn standalone_imp(gen: &mut Gen, names: &[&str]) -> String { + gen.namespace = "Windows."; + gen.standalone = true; + gen.sys = true; + + let mut type_names = BTreeSet::new(); + let mut core_types = BTreeSet::new(); + let mut enums = BTreeSet::new(); + + for name in names { + let type_name = TypeName::parse(name); + let mut found = false; + + if let Some(def) = gen.reader.get(type_name).next() { + found = true; + type_names.insert(type_name); + let mut cfg = gen.reader.type_def_cfg(def, &[]); + core_types.append(&mut cfg.core_types); + for def in cfg.types.values().flatten() { + type_names.insert(gen.reader.type_def_type_name(*def)); + } + if gen.reader.type_def_kind(def) == TypeKind::Struct + && gen.reader.type_def_fields(def).next().is_none() + && gen.reader.type_def_guid(def).is_some() + { + core_types.insert(Type::GUID); + } + } + + if !found { + for method in gen.reader.namespace_functions(type_name.namespace) { + if found { + break; + } + let name = gen.reader.method_def_name(method); + if name == type_name.name { + found = true; + type_names.insert(type_name); + let mut cfg = gen + .reader + .signature_cfg(&gen.reader.method_def_signature(method, &[])); + core_types.append(&mut cfg.core_types); + for def in cfg.types.values().flatten() { + type_names.insert(gen.reader.type_def_type_name(*def)); + } + } + } + for field in gen.reader.namespace_constants(type_name.namespace) { + if found { + break; + } + let name = gen.reader.field_name(field); + if name == type_name.name { + found = true; + type_names.insert(type_name); + let mut cfg = gen.reader.field_cfg(field); + core_types.append(&mut cfg.core_types); + for def in cfg.types.values().flatten() { + type_names.insert(gen.reader.type_def_type_name(*def)); + } + } + } + } + + if !found { + for def in gen + .reader + .namespace_types(type_name.namespace, &Default::default()) + { + if found { + break; + } + if gen.reader.type_def_kind(def) == TypeKind::Enum { + for field in gen.reader.type_def_fields(def) { + if found { + break; + } + let name = gen.reader.field_name(field); + if name == type_name.name { + found = true; + let enum_name = gen.reader.type_def_type_name(def); + type_names.insert(enum_name); + enums.insert((enum_name, type_name.name)); + } + } + } + } + } + } + + let mut sorted = SortedTokens::default(); + + for ty in core_types { + match ty { + Type::HRESULT => sorted.insert("HRESULT", quote! { pub type HRESULT = i32; }), + Type::String => sorted.insert( + "HSTRING", + quote! { pub type HSTRING = *mut ::core::ffi::c_void; }, + ), + Type::IUnknown => sorted.insert( + "IUnknown", + quote! { pub type IUnknown = *mut ::core::ffi::c_void; }, + ), + Type::IInspectable => sorted.insert( + "IInspectable", + quote! { pub type IInspectable = *mut ::core::ffi::c_void; }, + ), + Type::PSTR => sorted.insert("PSTR", quote! { pub type PSTR = *mut u8; }), + Type::PWSTR => sorted.insert("PWSTR", quote! { pub type PWSTR = *mut u16; }), + Type::PCSTR => sorted.insert("PCSTR", quote! { pub type PCSTR = *const u8; }), + Type::PCWSTR => sorted.insert("PCWSTR", quote! { pub type PCWSTR = *const u16; }), + Type::BSTR => sorted.insert("BSTR", quote! { pub type BSTR = *const u16; }), + Type::GUID => { + sorted.insert("GUID", quote! { + #[repr(C)] + pub struct GUID { + pub data1: u32, + pub data2: u16, + pub data3: u16, + pub data4: [u8; 8], + } + impl GUID { + pub const fn from_u128(uuid: u128) -> Self { + Self { data1: (uuid >> 96) as u32, data2: (uuid >> 80 & 0xffff) as u16, data3: (uuid >> 64 & 0xffff) as u16, data4: (uuid as u64).to_be_bytes() } + } + } + impl ::core::marker::Copy for GUID {} + impl ::core::clone::Clone for GUID { + fn clone(&self) -> Self { + *self + } + } + }); + } + _ => {} + } + } + + for type_name in type_names { + let mut found = false; + + for def in gen.reader.get(type_name) { + found = true; + let kind = gen.reader.type_def_kind(def); + + match kind { + TypeKind::Class | TypeKind::Interface => unimplemented!(), + TypeKind::Enum => { + sorted.insert(gen.reader.type_def_name(def), enums::gen(gen, def)); + } + TypeKind::Struct => { + if gen.reader.type_def_fields(def).next().is_none() { + if let Some(guid) = gen.reader.type_def_guid(def) { + let ident = to_ident(type_name.name); + let value = gen.guid(&guid); + let guid = gen.type_name(&Type::GUID); + sorted.insert( + type_name.name, + quote! { + pub const #ident: #guid = #value; + }, + ); + continue; + } + } + sorted.insert(gen.reader.type_def_name(def), structs::gen(gen, def)); + } + TypeKind::Delegate => { + sorted.insert(gen.reader.type_def_name(def), delegates::gen(gen, def)); + } + } + } + + if !found { + for method in gen.reader.namespace_functions(type_name.namespace) { + if found { + break; + } + let name = gen.reader.method_def_name(method); + if name == type_name.name { + found = true; + sorted.insert( + &format!(".{}.{name}", gen.reader.method_def_module_name(method)), + functions::gen(gen, method), + ); + } + } + for field in gen.reader.namespace_constants(type_name.namespace) { + if found { + break; + } + let name = gen.reader.field_name(field); + if name == type_name.name { + found = true; + sorted.insert(name, constants::gen(gen, field)); + } + } + } + } + + for (enum_type, field_name) in enums { + if let Some(def) = gen.reader.get(enum_type).next() { + for field in gen.reader.type_def_fields(def) { + if gen.reader.field_name(field) == field_name { + let ident = to_ident(field_name); + let ty = to_ident(enum_type.name); + let constant = gen.reader.field_constant(field).unwrap(); + let value = gen.value(&gen.reader.constant_value(constant)); + + sorted.insert( + field_name, + quote! { + pub const #ident: #ty = #value; + }, + ); + + break; + } + } + } + } + + let mut tokens: TokenStream = format!( + r#"// Bindings generated by `windows-bindgen` {} + +"#, + std::env!("CARGO_PKG_VERSION") + ) + .into(); + + tokens.combine(&allow()); + + for value in sorted.0.values() { + tokens.combine(value); + } + + try_format(tokens.into_string()) +} + +#[derive(Default)] +struct SortedTokens(BTreeMap<String, TokenStream>); + +impl SortedTokens { + fn insert(&mut self, key: &str, tokens: TokenStream) { + self.0.entry(key.to_string()).or_default().combine(&tokens); + } +} diff --git a/vendor/windows-bindgen/src/structs.rs b/vendor/windows-bindgen/src/structs.rs new file mode 100644 index 000000000..89670bdb5 --- /dev/null +++ b/vendor/windows-bindgen/src/structs.rs @@ -0,0 +1,316 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.reader.type_def_is_contract(def) { + return quote! {}; + } + + if gen.reader.type_def_is_handle(def) { + return handles::gen(gen, def); + } + + gen_struct_with_name(gen, def, gen.reader.type_def_name(def), &Cfg::default()) +} + +fn gen_struct_with_name(gen: &Gen, def: TypeDef, struct_name: &str, cfg: &Cfg) -> TokenStream { + let name = to_ident(struct_name); + + if gen.reader.type_def_fields(def).next().is_none() { + let mut tokens = quote! { + #[repr(C)] + pub struct #name(pub u8); + impl ::core::marker::Copy for #name {} + impl ::core::clone::Clone for #name { + fn clone(&self) -> Self { + *self + } + } + }; + if !gen.sys { + tokens.combine("e! { + impl ::windows::core::TypeKind for #name { + type TypeKind = ::windows::core::CopyType; + } + }); + } + return tokens; + } + + let flags = gen.reader.type_def_flags(def); + let cfg = cfg.union(&gen.reader.type_def_cfg(def, &[])); + + let repr = if let Some(layout) = gen.reader.type_def_class_layout(def) { + let packing = Literal::usize_unsuffixed(gen.reader.class_layout_packing_size(layout)); + quote! { #[repr(C, packed(#packing))] } + } else { + quote! { #[repr(C)] } + }; + + let fields = gen.reader.type_def_fields(def).map(|f| { + let name = to_ident(gen.reader.field_name(f)); + let ty = gen.reader.field_type(f, Some(def)); + + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + quote! {} + } else if !gen.sys + && flags.contains(TypeAttributes::EXPLICIT_LAYOUT) + && !gen.reader.field_is_copyable(f, def) + { + // Rust can't tell that the type is copyable and won't accept windows::core::ManuallyDrop + let ty = gen.type_default_name(&ty); + quote! { pub #name: ::std::mem::ManuallyDrop<#ty>, } + } else if !gen.sys + && !flags.contains(TypeAttributes::WINRT) + && !gen.reader.field_is_blittable(f, def) + { + if let Type::Win32Array((ty, len)) = ty { + let ty = gen.type_default_name(&ty); + quote! { pub #name: [::std::mem::ManuallyDrop<#ty>; #len], } + } else { + let ty = gen.type_default_name(&ty); + quote! { pub #name: ::std::mem::ManuallyDrop<#ty>, } + } + } else { + let ty = gen.type_default_name(&ty); + quote! { pub #name: #ty, } + } + }); + + let struct_or_union = if flags.contains(TypeAttributes::EXPLICIT_LAYOUT) { + quote! { union } + } else { + quote! { struct } + }; + + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + let mut tokens = quote! { + #repr + #doc + #features + pub #struct_or_union #name {#(#fields)*} + }; + + tokens.combine(&gen_struct_constants(gen, def, &name, &cfg)); + tokens.combine(&gen_copy_clone(gen, def, &name, &cfg)); + tokens.combine(&gen_debug(gen, def, &name, &cfg)); + tokens.combine(&gen_windows_traits(gen, def, &name, &cfg)); + tokens.combine(&gen_compare_traits(gen, def, &name, &cfg)); + + if !gen.sys { + tokens.combine("e! { + #features + impl ::core::default::Default for #name { + fn default() -> Self { + unsafe { ::core::mem::zeroed() } + } + } + }); + } + + for (index, nested_type) in gen.reader.nested_types(def).enumerate() { + let nested_name = format!("{struct_name}_{index}"); + tokens.combine(&gen_struct_with_name(gen, nested_type, &nested_name, &cfg)); + } + + tokens +} + +fn gen_windows_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { + if gen.sys { + quote! {} + } else { + let features = gen.cfg_features(cfg); + let is_copy = gen.reader.type_def_is_blittable(def); + + let type_kind = if is_copy { + quote! { CopyType } + } else { + quote! { ValueType } + }; + + let mut tokens = quote! { + #features + impl ::windows::core::TypeKind for #name { + type TypeKind = ::windows::core::#type_kind; + } + }; + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + let signature = + Literal::byte_string(gen.reader.type_def_signature(def, &[]).as_bytes()); + + tokens.combine("e! { + #features + impl ::windows::core::RuntimeType for #name { + const SIGNATURE: ::windows::imp::ConstBuffer = ::windows::imp::ConstBuffer::from_slice(#signature); + } + }); + } + + tokens + } +} + +fn gen_compare_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { + let features = gen.cfg_features(cfg); + + if gen.sys + || gen.reader.type_def_has_explicit_layout(def) + || gen.reader.type_def_has_packing(def) + || gen.reader.type_def_has_callback(def) + { + quote! {} + } else { + let fields = gen.reader.type_def_fields(def).filter_map(|f| { + let name = to_ident(gen.reader.field_name(f)); + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + None + } else { + Some(quote! { self.#name == other.#name }) + } + }); + + quote! { + #features + impl ::core::cmp::PartialEq for #name { + fn eq(&self, other: &Self) -> bool { + #(#fields)&&* + } + } + #features + impl ::core::cmp::Eq for #name {} + } + } +} + +fn gen_debug(gen: &Gen, def: TypeDef, ident: &TokenStream, cfg: &Cfg) -> TokenStream { + if gen.sys + || gen.reader.type_def_has_explicit_layout(def) + || gen.reader.type_def_has_packing(def) + { + quote! {} + } else { + let name = ident.as_str(); + let features = gen.cfg_features(cfg); + + let fields = gen.reader.type_def_fields(def).filter_map(|f| { + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + None + } else { + let name = gen.reader.field_name(f); + let ident = to_ident(name); + let ty = gen.reader.field_type(f, Some(def)); + if gen.reader.type_has_callback(&ty) { + None + } else { + Some(quote! { .field(#name, &self.#ident) }) + } + } + }); + + quote! { + #features + impl ::core::fmt::Debug for #ident { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_struct(#name) #(#fields)* .finish() + } + } + } + } +} + +fn gen_copy_clone(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { + let features = gen.cfg_features(cfg); + + if gen.sys || gen.reader.type_def_is_copyable(def) { + quote! { + #features + impl ::core::marker::Copy for #name {} + #features + impl ::core::clone::Clone for #name { + fn clone(&self) -> Self { + *self + } + } + } + } else if gen.reader.type_def_class_layout(def).is_some() { + // Don't support copy/clone of packed structs: https://github.com/rust-lang/rust/issues/82523 + quote! {} + } else if !gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + quote! { + #features + impl ::core::clone::Clone for #name { + fn clone(&self) -> Self { + unsafe { ::core::mem::transmute_copy(self) } + } + } + } + } else { + let fields = gen.reader.type_def_fields(def).map(|f| { + let name = to_ident(gen.reader.field_name(f)); + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + quote! {} + } else if gen.reader.field_is_blittable(f, def) { + quote! { #name: self.#name } + } else { + quote! { #name: self.#name.clone() } + } + }); + + quote! { + #features + impl ::core::clone::Clone for #name { + fn clone(&self) -> Self { + Self { #(#fields),* } + } + } + } + } +} + +fn gen_struct_constants( + gen: &Gen, + def: TypeDef, + struct_name: &TokenStream, + cfg: &Cfg, +) -> TokenStream { + let features = gen.cfg_features(cfg); + + let constants = gen.reader.type_def_fields(def).filter_map(|f| { + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + if let Some(constant) = gen.reader.field_constant(f) { + let name = to_ident(gen.reader.field_name(f)); + let value = gen.typed_value(&gen.reader.constant_value(constant)); + + return Some(quote! { + pub const #name: #value; + }); + } + } + + None + }); + + let mut tokens = quote! { #(#constants)* }; + + if !tokens.is_empty() { + tokens = quote! { + #features + impl #struct_name { + #tokens + } + }; + } + + tokens +} diff --git a/vendor/windows-bindgen/src/try_format.rs b/vendor/windows-bindgen/src/try_format.rs new file mode 100644 index 000000000..493a8a842 --- /dev/null +++ b/vendor/windows-bindgen/src/try_format.rs @@ -0,0 +1,31 @@ +pub fn try_format(tokens: String) -> String { + use std::io::Write; + + let Ok(mut child) = std::process::Command::new("rustfmt").stdin(std::process::Stdio::piped()).stdout(std::process::Stdio::piped()).stderr(std::process::Stdio::null()).spawn() else { + return tokens; + }; + + let Some(mut stdin) = child.stdin.take() else { + return tokens; + }; + + if stdin.write_all(tokens.as_bytes()).is_err() { + return tokens; + } + + drop(stdin); + + let Ok(output) = child.wait_with_output() else { + return tokens; + }; + + if !output.status.success() { + return tokens; + } + + if let Ok(result) = String::from_utf8(output.stdout) { + result + } else { + tokens + } +} diff --git a/vendor/windows-bindgen/src/winrt_methods.rs b/vendor/windows-bindgen/src/winrt_methods.rs new file mode 100644 index 000000000..457f70c38 --- /dev/null +++ b/vendor/windows-bindgen/src/winrt_methods.rs @@ -0,0 +1,258 @@ +use super::*; + +// TODO take Signature instead of MethodDef (wherever MethodDef is found) +pub fn gen( + gen: &Gen, + def: TypeDef, + generic_types: &[Type], + kind: InterfaceKind, + method: MethodDef, + method_names: &mut MethodNames, + virtual_names: &mut MethodNames, +) -> TokenStream { + let signature = gen.reader.method_def_signature(method, generic_types); + let params = &signature.params; + let name = method_names.add(gen, method); + let interface_name = gen.type_def_name(def, generic_types); + let vname = virtual_names.add(gen, method); + let generics = gen.constraint_generics(params); + let where_clause = gen.where_clause(params); + let mut cfg = gen.reader.signature_cfg(&signature); + gen.reader + .type_def_cfg_combine(def, generic_types, &mut cfg); + let doc = gen.cfg_method_doc(&cfg); + let features = gen.cfg_features(&cfg); + let args = gen_winrt_abi_args(gen, params); + let params = gen_winrt_params(gen, params); + + let return_type_tokens = if let Some(return_type) = &signature.return_type { + let tokens = gen.type_name(return_type); + if return_type.is_winrt_array() { + quote! { ::windows::core::Array<#tokens> } + } else { + quote! { #tokens } + } + } else { + quote! { () } + }; + + let return_arg = if let Some(return_type) = &signature.return_type { + if return_type.is_winrt_array() { + let return_type = gen.type_name(return_type); + quote! { ::windows::core::Array::<#return_type>::set_abi_len(::std::mem::transmute(&mut result__)), result__.as_mut_ptr() as *mut _ as _ } + } else { + quote! { &mut result__ } + } + } else { + quote! {} + }; + + let vcall = if let Some(return_type) = &signature.return_type { + if return_type.is_winrt_array() { + 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()) + } + } else { + let return_type = gen.type_name(return_type); + quote! { + let mut result__ = ::windows::core::zeroed::<#return_type>(); + (::windows::core::Interface::vtable(this).#vname)(::windows::core::Interface::as_raw(this), #args #return_arg) + .from_abi(result__) + } + } + } else { + quote! { + (::windows::core::Interface::vtable(this).#vname)(::windows::core::Interface::as_raw(this), #args).ok() + } + }; + + match kind { + InterfaceKind::Default => quote! { + #doc + #features + pub fn #name<#generics>(&self, #params) -> ::windows::core::Result<#return_type_tokens> #where_clause { + let this = self; + unsafe { + #vcall + } + } + }, + InterfaceKind::None | InterfaceKind::Base | InterfaceKind::Overridable => { + quote! { + #doc + #features + pub fn #name<#generics>(&self, #params) -> ::windows::core::Result<#return_type_tokens> #where_clause { + let this = &::windows::core::ComInterface::cast::<#interface_name>(self)?; + unsafe { + #vcall + } + } + } + } + InterfaceKind::Static => { + quote! { + #doc + #features + pub fn #name<#generics>(#params) -> ::windows::core::Result<#return_type_tokens> #where_clause { + Self::#interface_name(|this| unsafe { #vcall }) + } + } + } + } +} + +fn gen_winrt_params(gen: &Gen, params: &[SignatureParam]) -> TokenStream { + let mut result = quote! {}; + + let mut generic_params = gen.generic_params(params); + for param in params.iter() { + let name = gen.param_name(param.def); + let kind = gen.type_name(¶m.ty); + let default_type = gen.type_default_name(¶m.ty); + + if gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if param.ty.is_winrt_array() { + result.combine("e! { #name: &[#default_type], }); + } else if gen.reader.signature_param_is_convertible(param) { + let (position, _) = generic_params.next().unwrap(); + let kind: TokenStream = format!("P{position}").into(); + result.combine("e! { #name: #kind, }); + } else if gen.reader.type_is_blittable(¶m.ty) { + result.combine("e! { #name: #kind, }); + } else { + result.combine("e! { #name: &#kind, }); + } + } else if param.ty.is_winrt_array() { + result.combine("e! { #name: &mut [#default_type], }); + } else if param.ty.is_winrt_array_ref() { + result.combine("e! { #name: &mut ::windows::core::Array<#kind>, }); + } else { + result.combine("e! { #name: &mut #default_type, }); + } + } + + result +} + +fn gen_winrt_abi_args(gen: &Gen, params: &[SignatureParam]) -> TokenStream { + let mut tokens = TokenStream::new(); + for param in params { + let name = gen.param_name(param.def); + + let param = if gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if param.ty.is_winrt_array() { + if gen.reader.type_is_blittable(¶m.ty) { + quote! { #name.len() as u32, #name.as_ptr(), } + } else { + quote! { #name.len() as u32, ::core::mem::transmute(#name.as_ptr()), } + } + } else if gen.reader.signature_param_is_failible_param(param) { + quote! { #name.try_into_param()?.abi(), } + } else if gen.reader.signature_param_is_borrowed(param) { + quote! { #name.into_param().abi(), } + } else if gen.reader.type_is_blittable(¶m.ty) { + if param.ty.is_winrt_const_ref() { + quote! { &#name, } + } else { + quote! { #name, } + } + } else { + quote! { ::core::mem::transmute_copy(#name), } + } + } else if param.ty.is_winrt_array() { + if gen.reader.type_is_blittable(¶m.ty) { + quote! { #name.len() as u32, #name.as_mut_ptr(), } + } else { + quote! { #name.len() as u32, ::core::mem::transmute_copy(&#name), } + } + } else if param.ty.is_winrt_array_ref() { + quote! { #name.set_abi_len(), #name as *mut _ as _, } + } else if gen.reader.type_is_blittable(¶m.ty) { + quote! { #name, } + } else { + quote! { #name as *mut _ as _, } + }; + tokens.combine(¶m); + } + tokens +} + +pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream { + let invoke_args = sig + .params + .iter() + .map(|param| gen_winrt_invoke_arg(gen, param)); + + match &sig.return_type { + Some(return_type) if return_type.is_winrt_array() => { + quote! { + match #inner(#(#invoke_args,)*) { + ::core::result::Result::Ok(ok__) => { + let (ok_data__, ok_data_len__) = ok__.into_abi(); + // use `core::ptr::write` since `result` could be uninitialized + ::core::ptr::write(result__, ok_data__); + ::core::ptr::write(result_size__, ok_data_len__); + ::windows::core::HRESULT(0) + } + ::core::result::Result::Err(err) => err.into() + } + } + } + Some(_) => { + quote! { + match #inner(#(#invoke_args,)*) { + ::core::result::Result::Ok(ok__) => { + // use `core::ptr::write` since `result` could be uninitialized + ::core::ptr::write(result__, ::core::mem::transmute_copy(&ok__)); + ::core::mem::forget(ok__); + ::windows::core::HRESULT(0) + } + ::core::result::Result::Err(err) => err.into() + } + } + } + None => quote! { + #inner(#(#invoke_args,)*).into() + }, + } +} + +fn gen_winrt_invoke_arg(gen: &Gen, param: &SignatureParam) -> TokenStream { + let name = gen.param_name(param.def); + let abi_size_name: TokenStream = + format!("{}_array_size", gen.reader.param_name(param.def)).into(); + + if gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if param.ty.is_winrt_array() { + quote! { ::core::slice::from_raw_parts(::core::mem::transmute_copy(&#name), #abi_size_name as _) } + } else if gen.reader.type_is_primitive(¶m.ty) { + quote! { #name } + } else if param.ty.is_winrt_const_ref() { + quote! { ::core::mem::transmute_copy(&#name) } + } else if gen.reader.type_is_nullable(¶m.ty) { + quote! { ::windows::core::from_raw_borrowed(&#name) } + } else { + quote! { ::core::mem::transmute(&#name) } + } + } else if param.ty.is_winrt_array() { + quote! { ::core::slice::from_raw_parts_mut(::core::mem::transmute_copy(&#name), #abi_size_name as _) } + } else if param.ty.is_winrt_array_ref() { + quote! { ::windows::core::ArrayProxy::from_raw_parts(::core::mem::transmute_copy(&#name), #abi_size_name).as_array() } + } else { + quote! { ::core::mem::transmute_copy(&#name) } + } +} |