From 1b4833c504738ac312103fc30024924bbc406fc1 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 1 Mar 2024 13:56:08 -0600 Subject: [PATCH] Add ability to prepend code to type generation (#2907) --- crates/libs/bindgen/src/args.rs | 6 +-- crates/libs/bindgen/src/rust/mod.rs | 14 ++++++ crates/libs/bindgen/src/rust/writer.rs | 12 ++++- .../src/Windows/Win32/Foundation/mod.rs | 3 ++ .../src/Windows/Win32/System/Rpc/mod.rs | 1 + .../samples/windows/create_window/src/main.rs | 2 +- crates/samples/windows/direct2d/src/main.rs | 4 +- crates/samples/windows/direct3d12/src/main.rs | 4 +- crates/tests/lib/tests/win.rs | 2 +- crates/tests/standalone/build.rs | 10 +++++ crates/tests/standalone/src/b_prepend.rs | 45 +++++++++++++++++++ crates/tests/standalone/src/lib.rs | 18 ++++++++ crates/tests/win32/tests/win32.rs | 4 +- crates/tools/windows/bindings.txt | 4 ++ 14 files changed, 116 insertions(+), 13 deletions(-) create mode 100644 crates/tests/standalone/src/b_prepend.rs diff --git a/crates/libs/bindgen/src/args.rs b/crates/libs/bindgen/src/args.rs index 74b2c6ed75..197ff2781f 100644 --- a/crates/libs/bindgen/src/args.rs +++ b/crates/libs/bindgen/src/args.rs @@ -10,11 +10,9 @@ where Ok(result) } +// This function is needed to avoid a recursion limit in the Rust compiler. fn from_string(result: &mut Vec, value: &str) -> Result<()> { - let value = if let Some((value, _)) = value.split_once('#') { value } else { value }; - - from_iter(result, value.split_whitespace().map(|arg| arg.to_string()))?; - Ok(()) + from_iter(result, value.split_whitespace().map(|arg| arg.to_string())) } fn from_iter(result: &mut Vec, args: I) -> Result<()> diff --git a/crates/libs/bindgen/src/rust/mod.rs b/crates/libs/bindgen/src/rust/mod.rs index 6f9f14a746..6c634a22eb 100644 --- a/crates/libs/bindgen/src/rust/mod.rs +++ b/crates/libs/bindgen/src/rust/mod.rs @@ -42,6 +42,20 @@ pub fn from_reader(reader: &'static metadata::Reader, mut config: std::collectio return Err(Error::new("cannot combine `implement` and `sys` configuration values")); } + config.retain(|key, value| { + if let Some(full_name) = key.strip_prefix("prepend:") { + if let Some(index) = full_name.rfind('.') { + let namespace = &full_name[0..index]; + let name = &full_name[index + 1..]; + if let Some(type_def) = reader.get_type_def(namespace, name).next() { + writer.prepend.insert(type_def, value.to_string()); + return false; + } + } + } + true + }); + if let Some((key, _)) = config.first_key_value() { return Err(Error::new(&format!("invalid configuration value `{key}`"))); } diff --git a/crates/libs/bindgen/src/rust/writer.rs b/crates/libs/bindgen/src/rust/writer.rs index be08949db6..64c883d875 100644 --- a/crates/libs/bindgen/src/rust/writer.rs +++ b/crates/libs/bindgen/src/rust/writer.rs @@ -20,6 +20,7 @@ pub struct Writer { pub minimal: bool, // strips out enumerators - in future possibly other helpers as well pub no_inner_attributes: bool, // skips the inner attributes at the start of the file pub vtbl: bool, // include minimal vtbl layout support for interfaces + pub prepend: std::collections::HashMap, } impl Writer { @@ -36,6 +37,7 @@ impl Writer { minimal: false, no_inner_attributes: false, vtbl: false, + prepend: Default::default(), } } @@ -75,12 +77,20 @@ impl Writer { } } pub fn type_def(&self, def: metadata::TypeDef) -> TokenStream { - match def.kind() { + let tokens = match def.kind() { metadata::TypeKind::Class => classes::writer(self, def), metadata::TypeKind::Interface => interfaces::writer(self, def), metadata::TypeKind::Enum => enums::writer(self, def), metadata::TypeKind::Struct => structs::writer(self, def), metadata::TypeKind::Delegate => delegates::writer(self, def), + }; + + if let Some(prepend) = self.prepend.get(&def) { + let mut combined = TokenStream::from(prepend); + combined.combine(&tokens); + combined + } else { + tokens } } diff --git a/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs b/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs index c184b70f39..7b6d146e34 100644 --- a/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/Foundation/mod.rs @@ -10490,6 +10490,7 @@ impl ::core::fmt::Debug for WAIT_EVENT { f.debug_tuple("WAIT_EVENT").field(&self.0).finish() } } +#[must_use] #[repr(transparent)] #[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::marker::Copy, ::core::clone::Clone, ::core::default::Default)] pub struct WIN32_ERROR(pub u32); @@ -10530,6 +10531,7 @@ impl ::core::default::Default for APP_LOCAL_DEVICE_ID { unsafe { ::core::mem::zeroed() } } } +#[must_use] #[repr(transparent)] #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] pub struct BOOL(pub i32); @@ -11161,6 +11163,7 @@ impl ::core::default::Default for LUID { unsafe { ::core::mem::zeroed() } } } +#[must_use] #[repr(transparent)] #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] pub struct NTSTATUS(pub i32); diff --git a/crates/libs/windows/src/Windows/Win32/System/Rpc/mod.rs b/crates/libs/windows/src/Windows/Win32/System/Rpc/mod.rs index 81869e4239..2a424e568d 100644 --- a/crates/libs/windows/src/Windows/Win32/System/Rpc/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/Rpc/mod.rs @@ -3810,6 +3810,7 @@ impl ::core::fmt::Debug for RPC_NOTIFICATION_TYPES { f.debug_tuple("RPC_NOTIFICATION_TYPES").field(&self.0).finish() } } +#[must_use] #[repr(transparent)] #[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::marker::Copy, ::core::clone::Clone, ::core::default::Default)] pub struct RPC_STATUS(pub i32); diff --git a/crates/samples/windows/create_window/src/main.rs b/crates/samples/windows/create_window/src/main.rs index 600baa3b89..73c097968b 100644 --- a/crates/samples/windows/create_window/src/main.rs +++ b/crates/samples/windows/create_window/src/main.rs @@ -53,7 +53,7 @@ extern "system" fn wndproc(window: HWND, message: u32, wparam: WPARAM, lparam: L match message { WM_PAINT => { println!("WM_PAINT"); - ValidateRect(window, None); + _ = ValidateRect(window, None); LRESULT(0) } WM_DESTROY => { diff --git a/crates/samples/windows/direct2d/src/main.rs b/crates/samples/windows/direct2d/src/main.rs index 4dba37faae..33b991dd30 100644 --- a/crates/samples/windows/direct2d/src/main.rs +++ b/crates/samples/windows/direct2d/src/main.rs @@ -342,7 +342,7 @@ impl Window { let mut ps = PAINTSTRUCT::default(); BeginPaint(self.handle, &mut ps); self.render().unwrap(); - EndPaint(self.handle, &ps); + _ = EndPaint(self.handle, &ps); LRESULT(0) } WM_SIZE => { @@ -425,7 +425,7 @@ impl Window { DispatchMessageA(&message); } } else { - GetMessageA(&mut message, None, 0, 0); + _ = GetMessageA(&mut message, None, 0, 0); if message.message == WM_QUIT { return Ok(()); diff --git a/crates/samples/windows/direct3d12/src/main.rs b/crates/samples/windows/direct3d12/src/main.rs index 4ac091643c..d4af18f63b 100644 --- a/crates/samples/windows/direct3d12/src/main.rs +++ b/crates/samples/windows/direct3d12/src/main.rs @@ -103,14 +103,14 @@ where }; sample.bind_to_window(&hwnd)?; - unsafe { ShowWindow(hwnd, SW_SHOW) }; + unsafe { _ = ShowWindow(hwnd, SW_SHOW) }; loop { let mut message = MSG::default(); if unsafe { PeekMessageA(&mut message, None, 0, 0, PM_REMOVE) }.into() { unsafe { - TranslateMessage(&message); + _ = TranslateMessage(&message); DispatchMessageA(&message); } diff --git a/crates/tests/lib/tests/win.rs b/crates/tests/lib/tests/win.rs index e96a6c0e3f..844dabbd91 100644 --- a/crates/tests/lib/tests/win.rs +++ b/crates/tests/lib/tests/win.rs @@ -14,7 +14,7 @@ fn linker() -> Result<()> { #[test] fn gdi() { unsafe { - AlphaBlend( + _ = AlphaBlend( HDC::default(), 0, 0, diff --git a/crates/tests/standalone/build.rs b/crates/tests/standalone/build.rs index 9464470760..1f011038be 100644 --- a/crates/tests/standalone/build.rs +++ b/crates/tests/standalone/build.rs @@ -165,6 +165,16 @@ fn main() { "src/b_vtbl_4.rs", &["Windows.Win32.System.Com.IPersistFile"], ); + + riddle( + "src/b_prepend.rs", + &["Windows.Foundation.DateTime"], + &[ + "flatten", + "minimal", + "prepend:Windows.Foundation.DateTime=#[derive(std::cmp::PartialOrd,std::cmp::Ord)]", + ], + ); } fn write_sys(output: &str, filter: &[&str]) { diff --git a/crates/tests/standalone/src/b_prepend.rs b/crates/tests/standalone/src/b_prepend.rs new file mode 100644 index 0000000000..6f21f10ecf --- /dev/null +++ b/crates/tests/standalone/src/b_prepend.rs @@ -0,0 +1,45 @@ +// Bindings generated by `windows-bindgen` 0.54.0 + +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] +#[derive(std::cmp::PartialOrd, std::cmp::Ord)] +#[repr(C)] +pub struct DateTime { + pub UniversalTime: i64, +} +impl ::core::marker::Copy for DateTime {} +impl ::core::clone::Clone for DateTime { + fn clone(&self) -> Self { + *self + } +} +impl ::core::fmt::Debug for DateTime { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_struct("DateTime") + .field("UniversalTime", &self.UniversalTime) + .finish() + } +} +impl ::windows_core::TypeKind for DateTime { + type TypeKind = ::windows_core::CopyType; +} +impl ::windows_core::RuntimeType for DateTime { + const SIGNATURE: ::windows_core::imp::ConstBuffer = + ::windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.DateTime;i8)"); +} +impl ::core::cmp::PartialEq for DateTime { + fn eq(&self, other: &Self) -> bool { + self.UniversalTime == other.UniversalTime + } +} +impl ::core::cmp::Eq for DateTime {} +impl ::core::default::Default for DateTime { + fn default() -> Self { + unsafe { ::core::mem::zeroed() } + } +} diff --git a/crates/tests/standalone/src/lib.rs b/crates/tests/standalone/src/lib.rs index 5dedc55e7b..fc399ec707 100644 --- a/crates/tests/standalone/src/lib.rs +++ b/crates/tests/standalone/src/lib.rs @@ -18,6 +18,7 @@ mod b_none; mod b_overloads; mod b_pcstr; mod b_pcwstr; +mod b_prepend; mod b_pstr; mod b_pwstr; mod b_std; @@ -184,3 +185,20 @@ fn from_included() { included::GetVersion(); } } + +#[test] +fn prepend() { + use b_prepend::*; + let mut dates = [ + DateTime { UniversalTime: 123 }, + DateTime { UniversalTime: 42 }, + ]; + dates.sort(); + assert_eq!( + &dates, + &[ + DateTime { UniversalTime: 42 }, + DateTime { UniversalTime: 123 } + ] + ); +} diff --git a/crates/tests/win32/tests/win32.rs b/crates/tests/win32/tests/win32.rs index 188b531411..c471c1ab4b 100644 --- a/crates/tests/win32/tests/win32.rs +++ b/crates/tests/win32/tests/win32.rs @@ -182,7 +182,7 @@ fn com_inheritance() { assert!(factory.IsCurrent().as_bool()); // IDXGIFactory2 - factory.IsWindowedStereoEnabled(); + _ = factory.IsWindowedStereoEnabled(); // IDXGIFactory3 assert!(factory.GetCreationFlags() == 0); @@ -202,7 +202,7 @@ fn com_inheritance() { #[test] fn onecore_imports() -> windows::core::Result<()> { unsafe { - HasExpandedResources()?; + _ = HasExpandedResources()?; let uri = CreateUri(w!("http://kennykerr.ca"), URI_CREATE_FLAGS::default(), 0)?; diff --git a/crates/tools/windows/bindings.txt b/crates/tools/windows/bindings.txt index 548d49c094..ff71ca73be 100644 --- a/crates/tools/windows/bindings.txt +++ b/crates/tools/windows/bindings.txt @@ -1,6 +1,10 @@ --in crates/libs/bindgen/default --out crates/libs/windows/src/lib.rs --config package +--config prepend:Windows.Win32.Foundation.WIN32_ERROR=#[must_use] +--config prepend:Windows.Win32.Foundation.BOOL=#[must_use] +--config prepend:Windows.Win32.Foundation.NTSTATUS=#[must_use] +--config prepend:Windows.Win32.System.Rpc.RPC_STATUS=#[must_use] --filter Windows