diff --git a/.gitattributes b/.gitattributes index a9567e6535..e98263ebcb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,3 +5,4 @@ *.winmd -text *.lib -text *.a -text +*.exe -text diff --git a/.github/actions/fix-environment/action.yml b/.github/actions/fix-environment/action.yml index 30ca782cdf..87e2d5464d 100644 --- a/.github/actions/fix-environment/action.yml +++ b/.github/actions/fix-environment/action.yml @@ -18,6 +18,9 @@ runs: - name: Configure environment shell: pwsh run: | + $vs_root = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` + -latest -property installationPath -format value + switch -Wildcard ("${{ matrix.target }}") { "*-pc-windows-gnu" @@ -26,27 +29,38 @@ runs: } "i686*" { - "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86" >> $env:GITHUB_PATH - ((Resolve-Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\*\bin\Hostx86\x86") + "${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22000.0\x86" >> $env:GITHUB_PATH + ((Resolve-Path "$vs_root\VC\Tools\MSVC\*\bin\Hostx86\x86") | Sort-Object -Descending | Select -First 1).ToString() >> $env:GITHUB_PATH } "x86_64*" { - "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64" >> $env:GITHUB_PATH - ((Resolve-Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\*\bin\Hostx64\x64") + "${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22000.0\x64" >> $env:GITHUB_PATH + ((Resolve-Path "$vs_root\VC\Tools\MSVC\*\bin\Hostx64\x64") | Sort-Object -Descending | Select -First 1).ToString() >> $env:GITHUB_PATH } "aarch64*" { - "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64" >> $env:GITHUB_PATH - ((Resolve-Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\*\bin\Hostx64\x64") + "${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22000.0\x64" >> $env:GITHUB_PATH + ((Resolve-Path "$vs_root\VC\Tools\MSVC\*\bin\Hostx64\x64") | Sort-Object -Descending | Select -First 1).ToString() >> $env:GITHUB_PATH } "*" { (Join-Path $env:GITHUB_WORKSPACE "target\debug\deps").ToString() >> $env:GITHUB_PATH (Join-Path $env:GITHUB_WORKSPACE "target\test\debug\deps").ToString() >> $env:GITHUB_PATH - "INCLUDE=C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\winrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\cppwinrt" ` + "INCLUDE=${env:ProgramFiles(x86)}\Windows Kits\10\include\10.0.22000.0\winrt;${env:ProgramFiles(x86)}\Windows Kits\10\include\10.0.22000.0\cppwinrt" ` >> $env:GITHUB_ENV } } + # Workaround to address several issues with windows-2022 runners: + # - Old mingw-w64-* binutils that prevent deterministic builds. + # - Missing llvm-dlltool in the native Windows LLVM package. + # - Missing mingw-w64 compiler packages. + - name: Update packages + shell: pwsh + run: | + C:\msys64\usr\bin\pacman.exe -S --noconfirm mingw-w64-x86_64-binutils + C:\msys64\usr\bin\pacman.exe -S --noconfirm mingw-w64-x86_64-llvm + C:\msys64\usr\bin\pacman.exe -S --noconfirm mingw-w64-i686-gcc + C:\msys64\usr\bin\pacman.exe -S --noconfirm mingw-w64-x86_64-gcc diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 38dda4ca3a..5936bbb2aa 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -13,7 +13,7 @@ env: jobs: check: - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: @@ -32,6 +32,8 @@ jobs: run: rustup component add clippy - name: Fix environment uses: ./.github/actions/fix-environment + - name: Clippy cppwinrt + run: cargo clippy -p cppwinrt - name: Clippy no_std run: cargo clippy -p no_std - name: Clippy riddle @@ -50,6 +52,8 @@ jobs: run: cargo clippy -p sample_component_json_validator_winrt - name: Clippy sample_component_json_validator_winrt_client run: cargo clippy -p sample_component_json_validator_winrt_client + - name: Clippy sample_component_json_validator_winrt_client_cpp + run: cargo clippy -p sample_component_json_validator_winrt_client_cpp - name: Clippy sample_consent run: cargo clippy -p sample_consent - name: Clippy sample_core_app diff --git a/.github/workflows/debugger_visualizer.yml b/.github/workflows/debugger_visualizer.yml index 6df42008b8..856eeeaf6b 100644 --- a/.github/workflows/debugger_visualizer.yml +++ b/.github/workflows/debugger_visualizer.yml @@ -13,7 +13,7 @@ env: jobs: check: - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: diff --git a/.github/workflows/lib.yml b/.github/workflows/lib.yml index 3f76c20db8..15367212c9 100644 --- a/.github/workflows/lib.yml +++ b/.github/workflows/lib.yml @@ -13,7 +13,7 @@ env: jobs: check: - runs-on: windows-2019 + runs-on: windows-2022 steps: - name: Checkout uses: actions/checkout@v4 @@ -27,22 +27,30 @@ jobs: set PATH=C:\msys64\mingw64\bin;%PATH% cargo run -p tool_gnu -- all + - name: Find Visual Studio + id: visual-studio + shell: pwsh + run: | + $path = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` + -latest -property installationPath -format value + "install_path=$path" | Out-File -FilePath $env:GITHUB_OUTPUT -Append + - name: Build i686_msvc shell: cmd run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat" x86 + call "${{steps.visual-studio.outputs.install_path}}\VC\Auxiliary\Build\vcvars32.bat" x86 cargo run -p tool_msvc - name: Build x86_64_msvc shell: cmd run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat" amd64 + call "${{steps.visual-studio.outputs.install_path}}\VC\Auxiliary\Build\vcvars32.bat" amd64 cargo run -p tool_msvc - name: Build aarch64_msvc shell: cmd run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat" amd64_arm64 + call "${{steps.visual-studio.outputs.install_path}}\VC\Auxiliary\Build\vcvars32.bat" amd64_arm64 cargo run -p tool_msvc - name: Upload libs @@ -60,7 +68,7 @@ jobs: - name: Check dumpbin shell: pwsh run: | - $VisualStudioRoot = & vswhere -latest -property installationPath -format value + $VisualStudioRoot = "${{steps.visual-studio.outputs.install_path}}" $DumpbinPath = Resolve-Path "$VisualStudioRoot\VC\Tools\MSVC\*\bin\*\x86\dumpbin.exe" | Select -ExpandProperty Path -First 1 $Tests = @( diff --git a/.github/workflows/msrv-windows.yml b/.github/workflows/msrv-windows.yml index faeb6202aa..ebd08bc1c4 100644 --- a/.github/workflows/msrv-windows.yml +++ b/.github/workflows/msrv-windows.yml @@ -17,7 +17,7 @@ jobs: matrix: rust: [1.70.0, stable, nightly] runs-on: - - windows-2019 + - windows-2022 - ubuntu-latest runs-on: ${{ matrix.runs-on }} steps: diff --git a/.github/workflows/no-default-features.yml b/.github/workflows/no-default-features.yml index 23e7ce54cf..4049e286c7 100644 --- a/.github/workflows/no-default-features.yml +++ b/.github/workflows/no-default-features.yml @@ -13,7 +13,7 @@ env: jobs: check: - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: @@ -30,6 +30,8 @@ jobs: run: rustup target add ${{ matrix.target }} - name: Fix environment uses: ./.github/actions/fix-environment + - name: Check cppwinrt + run: cargo check -p cppwinrt --no-default-features - name: Check windows run: cargo check -p windows --no-default-features - name: Check windows-bindgen diff --git a/.github/workflows/raw_dylib.yml b/.github/workflows/raw_dylib.yml index 6cd27939ad..7ff54f8ad9 100644 --- a/.github/workflows/raw_dylib.yml +++ b/.github/workflows/raw_dylib.yml @@ -13,7 +13,7 @@ env: jobs: check: - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index db5d776699..e24c3ec7f6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ env: jobs: check: - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: @@ -56,6 +56,8 @@ jobs: uses: ./.github/actions/fix-environment - name: Clean run: cargo clean + - name: Test cppwinrt + run: cargo test -p cppwinrt --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test no_std run: cargo test -p no_std --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test riddle @@ -74,6 +76,8 @@ jobs: run: cargo test -p sample_component_json_validator_winrt --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test sample_component_json_validator_winrt_client run: cargo test -p sample_component_json_validator_winrt_client --target ${{ matrix.target }} ${{ matrix.etc }} + - name: Test sample_component_json_validator_winrt_client_cpp + run: cargo test -p sample_component_json_validator_winrt_client_cpp --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test sample_consent run: cargo test -p sample_consent --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test sample_core_app @@ -152,12 +156,12 @@ jobs: run: cargo test -p test_alternate_success_code --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_arch run: cargo test -p test_arch --target ${{ matrix.target }} ${{ matrix.etc }} + - name: Clean + run: cargo clean - name: Test test_arch_feature run: cargo test -p test_arch_feature --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_array run: cargo test -p test_array --target ${{ matrix.target }} ${{ matrix.etc }} - - name: Clean - run: cargo clean - name: Test test_bcrypt run: cargo test -p test_bcrypt --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_bstr @@ -254,12 +258,12 @@ jobs: run: cargo test -p test_standalone --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_string_param run: cargo test -p test_string_param --target ${{ matrix.target }} ${{ matrix.etc }} + - name: Clean + run: cargo clean - name: Test test_structs run: cargo test -p test_structs --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_sys run: cargo test -p test_sys --target ${{ matrix.target }} ${{ matrix.etc }} - - name: Clean - run: cargo clean - name: Test test_targets run: cargo test -p test_targets --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_unions diff --git a/.gitignore b/.gitignore index 4c6fca839a..ca33c1fc2c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /target *.lock *.winmd +winrt diff --git a/crates/libs/bindgen/src/error.rs b/crates/libs/bindgen/src/error.rs index de2bf1d7a3..5227f4c213 100644 --- a/crates/libs/bindgen/src/error.rs +++ b/crates/libs/bindgen/src/error.rs @@ -20,7 +20,11 @@ impl From for std::io::Error { impl From for Error { fn from(error: syn::Error) -> Self { let start = error.span().start(); - Self { message: error.to_string(), span: Some((start.line, start.column)), ..Self::default() } + Self { + message: error.to_string(), + span: Some((start.line, start.column)), + ..Self::default() + } } } @@ -40,10 +44,16 @@ impl std::fmt::Display for Error { impl Error { pub(crate) fn new(message: &str) -> Self { - Self { message: message.to_string(), ..Self::default() } + Self { + message: message.to_string(), + ..Self::default() + } } pub(crate) fn with_path(self, path: &str) -> Self { - Self { path: path.to_string(), ..self } + Self { + path: path.to_string(), + ..self + } } } diff --git a/crates/libs/bindgen/src/lib.rs b/crates/libs/bindgen/src/lib.rs index 439b85a545..a331c476e3 100644 --- a/crates/libs/bindgen/src/lib.rs +++ b/crates/libs/bindgen/src/lib.rs @@ -80,7 +80,9 @@ where if format { if output.is_some() || !include.is_empty() || !exclude.is_empty() { - return Err(Error::new("`--format` cannot be combined with `--out` or `--filter`")); + return Err(Error::new( + "`--format` cannot be combined with `--out` or `--filter`", + )); } let input = filter_input(&input, &["rdl"])?; @@ -90,7 +92,10 @@ where } for path in &input { - read_file_text(path).and_then(|source| rdl::File::parse_str(&source)).and_then(|file| write_to_file(path, file.fmt())).map_err(|err| err.with_path(path))?; + read_file_text(path) + .and_then(|source| rdl::File::parse_str(&source)) + .and_then(|file| write_to_file(path, file.fmt())) + .map_err(|err| err.with_path(path))?; } return Ok(String::new()); @@ -121,7 +126,11 @@ where let elapsed = time.elapsed().as_secs_f32(); if elapsed > 0.1 { - Ok(format!(" Finished writing `{}` in {:.2}s", output, time.elapsed().as_secs_f32())) + Ok(format!( + " Finished writing `{}` in {:.2}s", + output, + time.elapsed().as_secs_f32() + )) } else { Ok(format!(" Finished writing `{}`", output,)) } @@ -149,7 +158,11 @@ fn filter_input(input: &[&str], extensions: &[&str]) -> Result> { } if path.is_dir() { - for entry in path.read_dir().map_err(|_| Error::new("failed to read directory").with_path(input))?.flatten() { + for entry in path + .read_dir() + .map_err(|_| Error::new("failed to read directory").with_path(input))? + .flatten() + { let path = entry.path(); if path.is_file() { @@ -168,15 +181,27 @@ fn read_input(input: &[&str]) -> Result> { let mut results = vec![]; if cfg!(feature = "metadata") { - results.push(metadata::File::new(std::include_bytes!("../default/Windows.winmd").to_vec()).unwrap()); - results.push(metadata::File::new(std::include_bytes!("../default/Windows.Win32.winmd").to_vec()).unwrap()); - results.push(metadata::File::new(std::include_bytes!("../default/Windows.Wdk.winmd").to_vec()).unwrap()); + results.push( + metadata::File::new(std::include_bytes!("../default/Windows.winmd").to_vec()).unwrap(), + ); + results.push( + metadata::File::new(std::include_bytes!("../default/Windows.Win32.winmd").to_vec()) + .unwrap(), + ); + results.push( + metadata::File::new(std::include_bytes!("../default/Windows.Wdk.winmd").to_vec()) + .unwrap(), + ); } else if input.is_empty() { return Err(Error::new("no inputs")); } for input in &input { - let file = if extension(input) == "winmd" { read_winmd_file(input)? } else { read_rdl_file(input)? }; + let file = if extension(input) == "winmd" { + read_winmd_file(input)? + } else { + read_rdl_file(input)? + }; results.push(file); } @@ -220,12 +245,16 @@ fn read_rdl_file(path: &str) -> Result { } fn read_winmd_file(path: &str) -> Result { - read_file_bytes(path).and_then(|bytes| metadata::File::new(bytes).ok_or_else(|| Error::new("failed to read .winmd format").with_path(path))) + read_file_bytes(path).and_then(|bytes| { + metadata::File::new(bytes) + .ok_or_else(|| Error::new("failed to read .winmd format").with_path(path)) + }) } fn write_to_file>(path: &str, contents: C) -> Result<()> { if let Some(parent) = std::path::Path::new(path).parent() { - std::fs::create_dir_all(parent).map_err(|_| Error::new("failed to create directory").with_path(path))?; + std::fs::create_dir_all(parent) + .map_err(|_| Error::new("failed to create directory").with_path(path))?; } std::fs::write(path, contents).map_err(|_| Error::new("failed to write file").with_path(path)) @@ -239,13 +268,18 @@ fn canonicalize(value: &str) -> Result { write_to_file(value, "")?; } - let path = std::fs::canonicalize(value).map_err(|_| Error::new("failed to find path").with_path(value))?; + let path = std::fs::canonicalize(value) + .map_err(|_| Error::new("failed to find path").with_path(value))?; if temp { - std::fs::remove_file(value).map_err(|_| Error::new("failed to remove temporary file").with_path(value))?; + std::fs::remove_file(value) + .map_err(|_| Error::new("failed to remove temporary file").with_path(value))?; } - let path = path.to_string_lossy().trim_start_matches(r"\\?\").to_string(); + let path = path + .to_string_lossy() + .trim_start_matches(r"\\?\") + .to_string(); match path.rsplit_once('.') { Some((file, extension)) => Ok(format!("{file}.{}", extension.to_lowercase())), @@ -258,5 +292,6 @@ fn extension(path: &str) -> &str { } fn directory(path: &str) -> &str { - path.rsplit_once(&['/', '\\']).map_or("", |(directory, _)| directory) + path.rsplit_once(&['/', '\\']) + .map_or("", |(directory, _)| directory) } diff --git a/crates/libs/bindgen/src/metadata.rs b/crates/libs/bindgen/src/metadata.rs index 7dc6c9e458..a345d30ad3 100644 --- a/crates/libs/bindgen/src/metadata.rs +++ b/crates/libs/bindgen/src/metadata.rs @@ -70,7 +70,19 @@ pub enum AsyncKind { } #[derive(Clone, PartialEq, Eq, Default)] -pub struct Guid(pub u32, pub u16, pub u16, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8); +pub struct Guid( + pub u32, + pub u16, + pub u16, + pub u8, + pub u8, + pub u8, + pub u8, + pub u8, + pub u8, + pub u8, + pub u8, +); impl Guid { pub fn from_args(args: &[(&str, Value)]) -> Self { @@ -92,29 +104,67 @@ impl Guid { rest => unimplemented!("{rest:?}"), } } - Self(unwrap_u32(&args[0].1), unwrap_u16(&args[1].1), unwrap_u16(&args[2].1), unwrap_u8(&args[3].1), unwrap_u8(&args[4].1), unwrap_u8(&args[5].1), unwrap_u8(&args[6].1), unwrap_u8(&args[7].1), unwrap_u8(&args[8].1), unwrap_u8(&args[9].1), unwrap_u8(&args[10].1)) + Self( + unwrap_u32(&args[0].1), + unwrap_u16(&args[1].1), + unwrap_u16(&args[2].1), + unwrap_u8(&args[3].1), + unwrap_u8(&args[4].1), + unwrap_u8(&args[5].1), + unwrap_u8(&args[6].1), + unwrap_u8(&args[7].1), + unwrap_u8(&args[8].1), + unwrap_u8(&args[9].1), + unwrap_u8(&args[10].1), + ) } pub fn from_string_args(args: &[&str]) -> Self { - Self(args[0].parse().unwrap(), args[1].parse().unwrap(), args[2].parse().unwrap(), args[3].parse().unwrap(), args[4].parse().unwrap(), args[5].parse().unwrap(), args[6].parse().unwrap(), args[7].parse().unwrap(), args[8].parse().unwrap(), args[9].parse().unwrap(), args[10].parse().unwrap()) + Self( + args[0].parse().unwrap(), + args[1].parse().unwrap(), + args[2].parse().unwrap(), + args[3].parse().unwrap(), + args[4].parse().unwrap(), + args[5].parse().unwrap(), + args[6].parse().unwrap(), + args[7].parse().unwrap(), + args[8].parse().unwrap(), + args[9].parse().unwrap(), + args[10].parse().unwrap(), + ) } } impl std::fmt::Debug for Guid { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:08x?}-{:04x?}-{:04x?}-{:02x?}{:02x?}-{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}", self.0, self.1, self.2, self.3, self.4, self.5, self.6, self.7, self.8, self.9, self.10) + write!( + f, + "{:08x?}-{:04x?}-{:04x?}-{:02x?}{:02x?}-{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}", + self.0, self.1, self.2, self.3, self.4, self.5, self.6, self.7, self.8, self.9, self.10 + ) } } impl SignatureParamKind { fn is_array(&self) -> bool { - matches!(self, Self::ArrayFixed(_) | Self::ArrayRelativeLen(_) | Self::ArrayRelativeByteLen(_) | Self::ArrayRelativePtr(_)) + matches!( + self, + Self::ArrayFixed(_) + | Self::ArrayRelativeLen(_) + | Self::ArrayRelativeByteLen(_) + | Self::ArrayRelativePtr(_) + ) } } impl SignatureParam { pub fn is_convertible(&self) -> bool { - !self.def.flags().contains(ParamAttributes::Out) && !self.ty.is_winrt_array() && !self.ty.is_pointer() && !self.kind.is_array() && (type_is_borrowed(&self.ty) || type_is_trivially_convertible(&self.ty)) + !self.def.flags().contains(ParamAttributes::Out) + && !self.ty.is_winrt_array() + && !self.ty.is_pointer() + && !self.kind.is_array() + && (type_is_borrowed(&self.ty) || type_is_trivially_convertible(&self.ty)) } fn is_retval(&self) -> bool { @@ -130,7 +180,11 @@ impl SignatureParam { return false; } let flags = self.def.flags(); - if flags.contains(ParamAttributes::In) || !flags.contains(ParamAttributes::Out) || flags.contains(ParamAttributes::Optional) || self.kind.is_array() { + if flags.contains(ParamAttributes::In) + || !flags.contains(ParamAttributes::Out) + || flags.contains(ParamAttributes::Optional) + || self.kind.is_array() + { return false; } if param_kind(self.def).is_array() { @@ -151,7 +205,10 @@ impl SignatureParam { impl Signature { pub fn kind(&self) -> SignatureKind { - if self.def.has_attribute("CanReturnMultipleSuccessValuesAttribute") { + if self + .def + .has_attribute("CanReturnMultipleSuccessValuesAttribute") + { return SignatureKind::PreserveSig; } match &self.return_type { @@ -160,7 +217,11 @@ impl Signature { Type::Name(TypeName::HResult) => { if self.params.len() >= 2 { if let Some((guid, object)) = signature_param_is_query(&self.params) { - if self.params[object].def.flags().contains(ParamAttributes::Optional) { + if self.params[object] + .def + .flags() + .contains(ParamAttributes::Optional) + { return SignatureKind::QueryOptional(QueryPosition { object, guid }); } else { return SignatureKind::Query(QueryPosition { object, guid }); @@ -173,7 +234,11 @@ impl Signature { SignatureKind::ResultVoid } } - Type::TypeDef(def, _) if def.type_name() == TypeName::BOOL && method_def_last_error(self.def) => SignatureKind::ResultVoid, + Type::TypeDef(def, _) + if def.type_name() == TypeName::BOOL && method_def_last_error(self.def) => + { + SignatureKind::ResultVoid + } _ if type_is_struct(&self.return_type) => SignatureKind::ReturnStruct, _ => SignatureKind::PreserveSig, } @@ -197,7 +262,9 @@ impl Signature { } pub fn type_def_invoke_method(row: TypeDef) -> MethodDef { - row.methods().find(|method| method.name() == "Invoke").expect("`Invoke` method not found") + row.methods() + .find(|method| method.name() == "Invoke") + .expect("`Invoke` method not found") } pub fn type_def_generics(def: TypeDef) -> Vec { @@ -227,8 +294,14 @@ pub fn method_def_signature(namespace: &str, row: MethodDef, generics: &[Type]) let mut ty = reader.type_from_blob(&mut blob, None, generics); if let Some(name) = param_or_enum(param) { - let def = reader.get_type_def(namespace, &name).next().expect("Enum not found"); - ty = Type::PrimitiveOrEnum(Box::new(ty), Box::new(Type::TypeDef(def, Vec::new()))); + let def = reader + .get_type_def(namespace, &name) + .next() + .expect("Enum not found"); + ty = Type::PrimitiveOrEnum( + Box::new(ty), + Box::new(Type::TypeDef(def, Vec::new())), + ); } if param_is_const || !is_output { @@ -238,7 +311,11 @@ pub fn method_def_signature(namespace: &str, row: MethodDef, generics: &[Type]) ty = ty.to_const_ptr(); } let kind = param_kind(param); - Some(SignatureParam { def: param, ty, kind }) + Some(SignatureParam { + def: param, + ty, + kind, + }) } }) .collect(); @@ -246,9 +323,13 @@ pub fn method_def_signature(namespace: &str, row: MethodDef, generics: &[Type]) for position in 0..params.len() { // Point len params back to the corresponding ptr params. match params[position].kind { - SignatureParamKind::ArrayRelativeLen(relative) | SignatureParamKind::ArrayRelativeByteLen(relative) => { + SignatureParamKind::ArrayRelativeLen(relative) + | SignatureParamKind::ArrayRelativeByteLen(relative) => { // The len params must be input only. - if !params[relative].def.flags().contains(ParamAttributes::Out) && position != relative && !params[relative].ty.is_pointer() { + if !params[relative].def.flags().contains(ParamAttributes::Out) + && position != relative + && !params[relative].ty.is_pointer() + { params[relative].kind = SignatureParamKind::ArrayRelativePtr(position); } else { params[position].kind = SignatureParamKind::Other; @@ -268,7 +349,8 @@ pub fn method_def_signature(namespace: &str, row: MethodDef, generics: &[Type]) // Finds sets of ptr params pointing at the same len param. for (position, param) in params.iter().enumerate() { match param.kind { - SignatureParamKind::ArrayRelativeLen(relative) | SignatureParamKind::ArrayRelativeByteLen(relative) => { + SignatureParamKind::ArrayRelativeLen(relative) + | SignatureParamKind::ArrayRelativeByteLen(relative) => { sets.entry(relative).or_default().push(position); } _ => {} @@ -301,9 +383,14 @@ pub fn method_def_signature(namespace: &str, row: MethodDef, generics: &[Type]) param.kind = SignatureParamKind::IntoParam; } else { let flags = param.def.flags(); - if param.ty.is_pointer() && (flags.contains(ParamAttributes::Optional) || param.def.has_attribute("ReservedAttribute")) { + if param.ty.is_pointer() + && (flags.contains(ParamAttributes::Optional) + || param.def.has_attribute("ReservedAttribute")) + { param.kind = SignatureParamKind::OptionalPointer; - } else if type_is_primitive(¶m.ty) && (!param.ty.is_pointer() || type_is_blittable(¶m.ty.deref())) { + } else if type_is_primitive(¶m.ty) + && (!param.ty.is_pointer() || type_is_blittable(¶m.ty.deref())) + { param.kind = SignatureParamKind::ValueType; } else if type_is_blittable(¶m.ty) { param.kind = SignatureParamKind::Blittable; @@ -312,7 +399,12 @@ pub fn method_def_signature(namespace: &str, row: MethodDef, generics: &[Type]) } } - Signature { def: row, params, return_type, call_flags } + Signature { + def: row, + params, + return_type, + call_flags, + } } fn param_kind(row: Param) -> SignatureParamKind { @@ -321,7 +413,9 @@ fn param_kind(row: Param) -> SignatureParamKind { "NativeArrayInfoAttribute" => { for (_, value) in attribute.args() { match value { - Value::I16(value) => return SignatureParamKind::ArrayRelativeLen(value as usize), + Value::I16(value) => { + return SignatureParamKind::ArrayRelativeLen(value as usize) + } Value::I32(value) => return SignatureParamKind::ArrayFixed(value as usize), _ => {} } @@ -346,19 +440,26 @@ fn param_or_enum(row: Param) -> Option { return None; } - row.find_attribute("AssociatedEnumAttribute").and_then(|attribute| { - for (_, arg) in attribute.args() { - if let Value::String(name) = arg { - return Some(name); + row.find_attribute("AssociatedEnumAttribute") + .and_then(|attribute| { + for (_, arg) in attribute.args() { + if let Value::String(name) = arg { + return Some(name); + } } - } - None - }) + None + }) } fn signature_param_is_query(params: &[SignatureParam]) -> Option<(usize, usize)> { - if let Some(guid) = params.iter().rposition(|param| param.ty == Type::ConstPtr(Box::new(Type::Name(TypeName::GUID)), 1) && !param.def.flags().contains(ParamAttributes::Out)) { - if let Some(object) = params.iter().rposition(|param| param.ty == Type::MutPtr(Box::new(Type::Void), 2) && param.def.has_attribute("ComOutPtrAttribute")) { + if let Some(guid) = params.iter().rposition(|param| { + param.ty == Type::ConstPtr(Box::new(Type::Name(TypeName::GUID)), 1) + && !param.def.flags().contains(ParamAttributes::Out) + }) { + if let Some(object) = params.iter().rposition(|param| { + param.ty == Type::MutPtr(Box::new(Type::Void), 2) + && param.def.has_attribute("ComOutPtrAttribute") + }) { return Some((guid, object)); } } @@ -377,7 +478,14 @@ fn method_def_last_error(row: MethodDef) -> bool { pub fn type_is_borrowed(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => !type_def_is_blittable(*row), - Type::Name(TypeName::BSTR) | Type::Name(TypeName::VARIANT) | Type::Name(TypeName::PROPVARIANT) | Type::Const(TypeName::PSTR) | Type::Const(TypeName::PWSTR) | Type::Object | Type::Name(TypeName::IUnknown) | Type::GenericParam(_) => true, + Type::Name(TypeName::BSTR) + | Type::Name(TypeName::VARIANT) + | Type::Name(TypeName::PROPVARIANT) + | Type::Const(TypeName::PSTR) + | Type::Const(TypeName::PWSTR) + | Type::Object + | Type::Name(TypeName::IUnknown) + | Type::GenericParam(_) => true, _ => false, } } @@ -412,7 +520,10 @@ pub fn type_def_has_callback(row: TypeDef) -> bool { return false; } fn check(row: TypeDef) -> bool { - if row.fields().any(|field| type_has_callback(&field.ty(Some(row)))) { + if row + .fields() + .any(|field| type_has_callback(&field.ty(Some(row)))) + { return true; } false @@ -421,7 +532,10 @@ pub fn type_def_has_callback(row: TypeDef) -> bool { if type_name.namespace().is_empty() { check(row) } else { - for row in row.reader().get_type_def(type_name.namespace(), type_name.name()) { + for row in row + .reader() + .get_type_def(type_name.namespace(), type_name.name()) + { if check(row) { return true; } @@ -431,7 +545,10 @@ pub fn type_def_has_callback(row: TypeDef) -> bool { } pub fn type_def_has_float(def: TypeDef) -> bool { - def.kind() == TypeKind::Struct && def.fields().any(|field| type_has_float(&field.ty(Some(def)))) + def.kind() == TypeKind::Struct + && def + .fields() + .any(|field| type_has_float(&field.ty(Some(def)))) } pub fn type_has_float(ty: &Type) -> bool { @@ -486,8 +603,15 @@ pub fn type_interfaces(ty: &Type) -> Vec { "StaticAttribute" | "ActivatableAttribute" => { for (_, arg) in attribute.args() { if let Value::TypeName(type_name) = arg { - let def = row.reader().get_type_def(type_name.namespace(), type_name.name()).next().expect("Type not found"); - result.push(Interface { ty: Type::TypeDef(def, Vec::new()), kind: InterfaceKind::Static }); + let def = row + .reader() + .get_type_def(type_name.namespace(), type_name.name()) + .next() + .expect("Type not found"); + result.push(Interface { + ty: Type::TypeDef(def, Vec::new()), + kind: InterfaceKind::Static, + }); break; } } @@ -519,7 +643,13 @@ pub fn field_is_copyable(row: Field, enclosing: TypeDef) -> bool { pub fn type_is_blittable(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => type_def_is_blittable(*row), - Type::String | Type::Name(TypeName::BSTR) | Type::Name(TypeName::VARIANT) | Type::Name(TypeName::PROPVARIANT) | Type::Object | Type::Name(TypeName::IUnknown) | Type::GenericParam(_) => false, + Type::String + | Type::Name(TypeName::BSTR) + | Type::Name(TypeName::VARIANT) + | Type::Name(TypeName::PROPVARIANT) + | Type::Object + | Type::Name(TypeName::IUnknown) + | Type::GenericParam(_) => false, Type::Win32Array(kind, _) => type_is_blittable(kind), Type::WinrtArray(kind) => type_is_blittable(kind), _ => true, @@ -529,7 +659,13 @@ pub fn type_is_blittable(ty: &Type) -> bool { fn type_is_copyable(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => type_def_is_copyable(*row), - Type::String | Type::Name(TypeName::BSTR) | Type::Name(TypeName::VARIANT) | Type::Name(TypeName::PROPVARIANT) | Type::Object | Type::Name(TypeName::IUnknown) | Type::GenericParam(_) => false, + Type::String + | Type::Name(TypeName::BSTR) + | Type::Name(TypeName::VARIANT) + | Type::Name(TypeName::PROPVARIANT) + | Type::Object + | Type::Name(TypeName::IUnknown) + | Type::GenericParam(_) => false, Type::Win32Array(kind, _) => type_is_copyable(kind), Type::WinrtArray(kind) => type_is_copyable(kind), _ => true, @@ -587,7 +723,23 @@ fn type_def_is_primitive(row: TypeDef) -> bool { pub fn type_is_primitive(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => type_def_is_primitive(*row), - Type::Bool | Type::Char | Type::I8 | Type::U8 | Type::I16 | Type::U16 | Type::I32 | Type::U32 | Type::I64 | Type::U64 | Type::F32 | Type::F64 | Type::ISize | Type::USize | Type::Name(TypeName::HResult) | Type::ConstPtr(_, _) | Type::MutPtr(_, _) => true, + Type::Bool + | Type::Char + | Type::I8 + | Type::U8 + | Type::I16 + | Type::U16 + | Type::I32 + | Type::U32 + | Type::I64 + | Type::U64 + | Type::F32 + | Type::F64 + | Type::ISize + | Type::USize + | Type::Name(TypeName::HResult) + | Type::ConstPtr(_, _) + | Type::MutPtr(_, _) => true, _ => false, } } @@ -608,7 +760,10 @@ pub fn type_def_has_explicit_layout(row: TypeDef) -> bool { if row.flags().contains(TypeAttributes::ExplicitLayout) { return true; } - if row.fields().any(|field| type_has_explicit_layout(&field.ty(Some(row)))) { + if row + .fields() + .any(|field| type_has_explicit_layout(&field.ty(Some(row)))) + { return true; } false @@ -617,7 +772,10 @@ pub fn type_def_has_explicit_layout(row: TypeDef) -> bool { if type_name.namespace().is_empty() { check(row) } else { - for row in row.reader().get_type_def(type_name.namespace(), type_name.name()) { + for row in row + .reader() + .get_type_def(type_name.namespace(), type_name.name()) + { if check(row) { return true; } @@ -642,7 +800,10 @@ pub fn type_def_has_packing(row: TypeDef) -> bool { if row.class_layout().is_some() { return true; } - if row.fields().any(|field| type_has_packing(&field.ty(Some(row)))) { + if row + .fields() + .any(|field| type_has_packing(&field.ty(Some(row)))) + { return true; } false @@ -651,7 +812,10 @@ pub fn type_def_has_packing(row: TypeDef) -> bool { if type_name.namespace().is_empty() { check(row) } else { - for row in row.reader().get_type_def(type_name.namespace(), type_name.name()) { + for row in row + .reader() + .get_type_def(type_name.namespace(), type_name.name()) + { if check(row) { return true; } @@ -660,15 +824,31 @@ pub fn type_def_has_packing(row: TypeDef) -> bool { } } -pub fn type_def_interfaces(def: TypeDef, generics: &[Type]) -> impl Iterator + '_ { +pub fn type_def_interfaces( + def: TypeDef, + generics: &[Type], +) -> impl Iterator + '_ { def.interface_impls().map(|imp| { - let kind = if imp.has_attribute("DefaultAttribute") { InterfaceKind::Default } else { InterfaceKind::None }; - Interface { kind, ty: imp.ty(generics) } + let kind = if imp.has_attribute("DefaultAttribute") { + InterfaceKind::Default + } else { + InterfaceKind::None + }; + Interface { + kind, + ty: imp.ty(generics), + } }) } pub fn type_def_default_interface(row: TypeDef) -> Option { - type_def_interfaces(row, &[]).find_map(move |interface| if interface.kind == InterfaceKind::Default { Some(interface.ty) } else { None }) + type_def_interfaces(row, &[]).find_map(move |interface| { + if interface.kind == InterfaceKind::Default { + Some(interface.ty) + } else { + None + } + }) } fn type_signature(ty: &Type) -> String { @@ -701,12 +881,20 @@ pub fn type_def_signature(row: TypeDef, generics: &[Type]) -> String { TypeKind::Interface => type_def_interface_signature(row, generics), TypeKind::Class => { if let Some(Type::TypeDef(default, generics)) = type_def_default_interface(row) { - format!("rc({};{})", row.type_name(), type_def_interface_signature(default, &generics)) + format!( + "rc({};{})", + row.type_name(), + type_def_interface_signature(default, &generics) + ) } else { unimplemented!(); } } - TypeKind::Enum => format!("enum({};{})", row.type_name(), type_signature(&row.underlying_type())), + TypeKind::Enum => format!( + "enum({};{})", + row.type_name(), + type_signature(&row.underlying_type()) + ), TypeKind::Struct => { let mut result = format!("struct({}", row.type_name()); for field in row.fields() { @@ -746,7 +934,8 @@ pub fn type_def_is_handle(row: TypeDef) -> bool { } pub fn type_def_guid(row: TypeDef) -> Option { - row.find_attribute("GuidAttribute").map(|attribute| Guid::from_args(&attribute.args())) + row.find_attribute("GuidAttribute") + .map(|attribute| Guid::from_args(&attribute.args())) } pub fn type_def_bases(mut row: TypeDef) -> Vec { @@ -754,7 +943,11 @@ pub fn type_def_bases(mut row: TypeDef) -> Vec { loop { match row.extends() { Some(base) if base != TypeName::Object => { - row = row.reader().get_type_def(base.namespace(), base.name()).next().expect("Type not found"); + row = row + .reader() + .get_type_def(base.namespace(), base.name()) + .next() + .expect("Type not found"); bases.push(row); } _ => break, diff --git a/crates/libs/bindgen/src/rdl/from_reader.rs b/crates/libs/bindgen/src/rdl/from_reader.rs index 0cbd831532..b1fb2d2239 100644 --- a/crates/libs/bindgen/src/rdl/from_reader.rs +++ b/crates/libs/bindgen/src/rdl/from_reader.rs @@ -1,11 +1,19 @@ use super::*; use tokens::{quote, to_ident, TokenStream}; -pub fn from_reader(reader: &'static metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { +pub fn from_reader( + reader: &'static metadata::Reader, + mut config: std::collections::BTreeMap<&str, &str>, + output: &str, +) -> Result<()> { let dialect = match config.remove("type") { Some("winrt") => Dialect::WinRT, Some("win32") => Dialect::Win32, - _ => return Err(Error::new("configuration value `type` must be `win32` or `winrt`")), + _ => { + return Err(Error::new( + "configuration value `type` must be `win32` or `winrt`", + )) + } }; let mut writer = Writer::new(reader, output, dialect); @@ -65,11 +73,23 @@ struct Writer { impl Writer { fn new(reader: &'static metadata::Reader, output: &str, dialect: Dialect) -> Self { - Self { reader, namespace: "", output: output.to_string(), dialect, split: false } + Self { + reader, + namespace: "", + output: output.to_string(), + dialect, + split: false, + } } fn with_namespace(&self, namespace: &'static str) -> Self { - Self { reader: self.reader, namespace, dialect: self.dialect, output: self.output.clone(), split: self.split } + Self { + reader: self.reader, + namespace, + dialect: self.dialect, + output: self.output.clone(), + split: self.split, + } } fn write_to_file(&self, output: &str, tokens: TokenStream) -> Result<()> { @@ -106,9 +126,16 @@ impl Writer { tokens } else { - let name = to_ident(tree.namespace.rsplit_once('.').map_or(tree.namespace, |(_, name)| name)); + let name = to_ident( + tree.namespace + .rsplit_once('.') + .map_or(tree.namespace, |(_, name)| name), + ); - let modules = tree.nested.values().map(|tree| self.with_namespace(tree.namespace).tree(tree)); + let modules = tree + .nested + .values() + .map(|tree| self.with_namespace(tree.namespace).tree(tree)); if tree.namespace.is_empty() { quote! { @@ -132,20 +159,30 @@ impl Writer { let mut types = vec![]; if !tree.namespace.is_empty() { - for item in self.reader.namespace_items(tree.namespace).filter(|item| match item { - metadata::Item::Type(def) => { - let winrt = def.flags().contains(metadata::TypeAttributes::WindowsRuntime); - match self.dialect { - Dialect::Win32 => !winrt, - Dialect::WinRT => winrt, + for item in self + .reader + .namespace_items(tree.namespace) + .filter(|item| match item { + metadata::Item::Type(def) => { + let winrt = def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime); + match self.dialect { + Dialect::Win32 => !winrt, + Dialect::WinRT => winrt, + } } - } - metadata::Item::Fn(_, _) | metadata::Item::Const(_) => self.dialect == Dialect::Win32, - }) { + metadata::Item::Fn(_, _) | metadata::Item::Const(_) => { + self.dialect == Dialect::Win32 + } + }) + { match item { metadata::Item::Type(def) => types.push(self.type_def(def)), metadata::Item::Const(field) => constants.push(self.constant(field)), - metadata::Item::Fn(method, namespace) => functions.push(self.function(method, namespace)), + metadata::Item::Fn(method, namespace) => { + functions.push(self.function(method, namespace)) + } } } } diff --git a/crates/libs/bindgen/src/rdl/mod.rs b/crates/libs/bindgen/src/rdl/mod.rs index da0add924c..d3f76d8660 100644 --- a/crates/libs/bindgen/src/rdl/mod.rs +++ b/crates/libs/bindgen/src/rdl/mod.rs @@ -152,7 +152,10 @@ fn winrt(input: syn::parse::ParseStream<'_>) -> syn::Result { } } - Err(syn::Error::new(input.span(), "A single `#![win32]` or `#![winrt]` attribute required")) + Err(syn::Error::new( + input.span(), + "A single `#![win32]` or `#![winrt]` attribute required", + )) } impl syn::parse::Parse for File { @@ -171,20 +174,34 @@ impl syn::parse::Parse for File { return Err(lookahead.error()); } } - Ok(Self { winrt, references, modules }) + Ok(Self { + winrt, + references, + modules, + }) } } impl Module { fn name(&self) -> &str { - self.namespace.rsplit_once('.').map_or(&self.namespace, |(_, name)| name) + self.namespace + .rsplit_once('.') + .map_or(&self.namespace, |(_, name)| name) } - fn parse(namespace: &str, winrt: bool, input: syn::parse::ParseStream<'_>) -> syn::Result { + fn parse( + namespace: &str, + winrt: bool, + input: syn::parse::ParseStream<'_>, + ) -> syn::Result { input.parse::()?; let name = input.parse::()?.to_string(); - let namespace = if namespace.is_empty() { name.to_string() } else { format!("{namespace}.{name}") }; + let namespace = if namespace.is_empty() { + name.to_string() + } else { + format!("{namespace}.{name}") + }; let content; syn::braced!(content in input); @@ -197,26 +214,45 @@ impl Module { } impl ModuleMember { - fn parse(namespace: &str, winrt: bool, input: syn::parse::ParseStream<'_>) -> syn::Result { + fn parse( + namespace: &str, + winrt: bool, + input: syn::parse::ParseStream<'_>, + ) -> syn::Result { let attributes: Vec = input.call(syn::Attribute::parse_outer)?; let lookahead = input.lookahead1(); if lookahead.peek(syn::Token![mod]) { if let Some(attribute) = attributes.first() { - return Err(syn::Error::new(attribute.span(), "`use` attributes not supported")); + return Err(syn::Error::new( + attribute.span(), + "`use` attributes not supported", + )); } - Ok(ModuleMember::Module(Module::parse(namespace, winrt, input)?)) + Ok(ModuleMember::Module(Module::parse( + namespace, winrt, input, + )?)) } else if lookahead.peek(interface) { - Ok(ModuleMember::Interface(Interface::parse(namespace, winrt, attributes, input)?)) + Ok(ModuleMember::Interface(Interface::parse( + namespace, winrt, attributes, input, + )?)) } else if lookahead.peek(syn::Token![struct]) { - Ok(ModuleMember::Struct(Struct::parse(namespace, winrt, attributes, input)?)) + Ok(ModuleMember::Struct(Struct::parse( + namespace, winrt, attributes, input, + )?)) } else if lookahead.peek(syn::Token![enum]) { - Ok(ModuleMember::Enum(Enum::parse(namespace, winrt, attributes, input)?)) + Ok(ModuleMember::Enum(Enum::parse( + namespace, winrt, attributes, input, + )?)) } else if lookahead.peek(class) { Ok(ModuleMember::Class(Class::parse(attributes, input)?)) } else if lookahead.peek(syn::Token![fn]) { - Ok(ModuleMember::Function(Function::parse(namespace, attributes, input)?)) + Ok(ModuleMember::Function(Function::parse( + namespace, attributes, input, + )?)) } else if lookahead.peek(syn::Token![const]) { - Ok(ModuleMember::Constant(Constant::parse(namespace, attributes, input)?)) + Ok(ModuleMember::Constant(Constant::parse( + namespace, attributes, input, + )?)) } else { Err(lookahead.error()) } @@ -224,7 +260,10 @@ impl ModuleMember { } impl Class { - fn parse(attributes: Vec, input: syn::parse::ParseStream<'_>) -> syn::Result { + fn parse( + attributes: Vec, + input: syn::parse::ParseStream<'_>, + ) -> syn::Result { input.parse::()?; let name = input.parse::()?.to_string(); let mut extends = Vec::new(); @@ -244,12 +283,22 @@ impl Class { } input.parse::()?; - Ok(Self { attributes, name, base, extends }) + Ok(Self { + attributes, + name, + base, + extends, + }) } } impl Interface { - fn parse(_namespace: &str, winrt: bool, attributes: Vec, input: syn::parse::ParseStream<'_>) -> syn::Result { + fn parse( + _namespace: &str, + winrt: bool, + attributes: Vec, + input: syn::parse::ParseStream<'_>, + ) -> syn::Result { input.parse::()?; let name = input.parse::()?.to_string(); @@ -281,12 +330,24 @@ impl Interface { while !content.is_empty() { methods.push(content.parse()?); } - Ok(Self { winrt, attributes, generics, extends, name, methods }) + Ok(Self { + winrt, + attributes, + generics, + extends, + name, + methods, + }) } } impl Struct { - fn parse(_namespace: &str, winrt: bool, attributes: Vec, input: syn::parse::ParseStream<'_>) -> syn::Result { + fn parse( + _namespace: &str, + winrt: bool, + attributes: Vec, + input: syn::parse::ParseStream<'_>, + ) -> syn::Result { // TODO: need to validate that the struct is valid according to the constraints of the winmd type system. // Same for the other types. That way we can spit out errors quickly for things like unnamed fields. let span = input.span(); @@ -308,12 +369,23 @@ impl Struct { }); } - Ok(Self { winrt, name, attributes, span, fields }) + Ok(Self { + winrt, + name, + attributes, + span, + fields, + }) } } impl Enum { - fn parse(_namespace: &str, winrt: bool, attributes: Vec, input: syn::parse::ParseStream<'_>) -> syn::Result { + fn parse( + _namespace: &str, + winrt: bool, + attributes: Vec, + input: syn::parse::ParseStream<'_>, + ) -> syn::Result { let mut item: syn::ItemEnum = input.parse()?; item.attrs = attributes; let name = item.ident.to_string(); @@ -322,7 +394,11 @@ impl Enum { } impl Constant { - fn parse(_namespace: &str, attributes: Vec, input: syn::parse::ParseStream<'_>) -> syn::Result { + fn parse( + _namespace: &str, + attributes: Vec, + input: syn::parse::ParseStream<'_>, + ) -> syn::Result { let mut item: syn::ItemConst = input.parse()?; item.attrs = attributes; let name = item.ident.to_string(); @@ -331,7 +407,11 @@ impl Constant { } impl Function { - fn parse(_namespace: &str, attributes: Vec, input: syn::parse::ParseStream<'_>) -> syn::Result { + fn parse( + _namespace: &str, + attributes: Vec, + input: syn::parse::ParseStream<'_>, + ) -> syn::Result { let mut item: syn::TraitItemFn = input.parse()?; item.attrs = attributes; let name = item.sig.ident.to_string(); diff --git a/crates/libs/bindgen/src/rdl/to_winmd.rs b/crates/libs/bindgen/src/rdl/to_winmd.rs index 88933a1ea9..4ce240dd90 100644 --- a/crates/libs/bindgen/src/rdl/to_winmd.rs +++ b/crates/libs/bindgen/src/rdl/to_winmd.rs @@ -21,7 +21,9 @@ pub fn rdl_to_winmd(file: &File) -> Result> { // or a type from a use declaration...? let mut collector = HashMap::>::new(); - file.modules.iter().for_each(|module| collect_module(&mut collector, module)); + file.modules + .iter() + .for_each(|module| collect_module(&mut collector, module)); // TODO: collect type names into hashmap (phase 1) and just drop clones of the IDL members into the collector @@ -30,23 +32,45 @@ pub fn rdl_to_winmd(file: &File) -> Result> { let mut writer = winmd::Writer::new("temp.winmd"); - collector.iter().for_each(|(namespace, members)| members.iter().for_each(|(name, member)| write_member(&mut writer, namespace, name, member))); + collector.iter().for_each(|(namespace, members)| { + members + .iter() + .for_each(|(name, member)| write_member(&mut writer, namespace, name, member)) + }); Ok(writer.into_stream()) } -fn collect_module<'a>(collector: &mut HashMap>, module: &'a Module) { - module.members.iter().for_each(|member| collect_member(collector, module, member)); +fn collect_module<'a>( + collector: &mut HashMap>, + module: &'a Module, +) { + module + .members + .iter() + .for_each(|member| collect_member(collector, module, member)); } -fn collect_member<'a>(collector: &mut HashMap>, module: &'a Module, member: &'a ModuleMember) { +fn collect_member<'a>( + collector: &mut HashMap>, + module: &'a Module, + member: &'a ModuleMember, +) { match member { ModuleMember::Module(module) => collect_module(collector, module), ModuleMember::Constant(_) | ModuleMember::Function(_) => { - collector.entry(module.namespace.to_string()).or_default().entry("Apis").or_insert(member.clone()); + collector + .entry(module.namespace.to_string()) + .or_default() + .entry("Apis") + .or_insert(member.clone()); } _ => { - collector.entry(module.namespace.to_string()).or_default().entry(member.name()).or_insert(member.clone()); + collector + .entry(module.namespace.to_string()) + .or_default() + .entry(member.name()) + .or_insert(member.clone()); } } } @@ -62,7 +86,9 @@ fn write_member(writer: &mut winmd::Writer, namespace: &str, name: &str, member: } fn write_interface(writer: &mut winmd::Writer, namespace: &str, name: &str, member: &Interface) { - let mut flags = metadata::TypeAttributes::Public | metadata::TypeAttributes::Interface | metadata::TypeAttributes::Abstract; + let mut flags = metadata::TypeAttributes::Public + | metadata::TypeAttributes::Interface + | metadata::TypeAttributes::Abstract; if member.winrt { flags |= metadata::TypeAttributes::WindowsRuntime @@ -90,22 +116,40 @@ fn write_interface(writer: &mut winmd::Writer, namespace: &str, name: &str, memb let ty = syn_type_path(namespace, &member.generics, type_path); let reference = match &ty { - winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => writer.insert_type_ref(&type_name.namespace, &type_name.name), + winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => { + writer.insert_type_ref(&type_name.namespace, &type_name.name) + } winmd::Type::TypeRef(_) => writer.insert_type_spec(ty), rest => unimplemented!("{rest:?}"), }; - writer.tables.InterfaceImpl.push(writer::InterfaceImpl { Class: writer.tables.TypeDef.len() as u32 - 1, Interface: reference }); + writer.tables.InterfaceImpl.push(writer::InterfaceImpl { + Class: writer.tables.TypeDef.len() as u32 - 1, + Interface: reference, + }); } for method in &member.methods { let signature = syn_signature(namespace, &member.generics, &method.sig); - let params: Vec = signature.params.iter().map(|param| param.ty.clone()).collect(); - - let signature_blob = writer.insert_method_sig(metadata::MethodCallAttributes(0), &signature.return_type, ¶ms); - - let flags = metadata::MethodAttributes::Abstract | metadata::MethodAttributes::HideBySig | metadata::MethodAttributes::HideBySig | metadata::MethodAttributes::NewSlot | metadata::MethodAttributes::Public | metadata::MethodAttributes::Virtual; + let params: Vec = signature + .params + .iter() + .map(|param| param.ty.clone()) + .collect(); + + let signature_blob = writer.insert_method_sig( + metadata::MethodCallAttributes(0), + &signature.return_type, + ¶ms, + ); + + let flags = metadata::MethodAttributes::Abstract + | metadata::MethodAttributes::HideBySig + | metadata::MethodAttributes::HideBySig + | metadata::MethodAttributes::NewSlot + | metadata::MethodAttributes::Public + | metadata::MethodAttributes::Virtual; writer.tables.MethodDef.push(winmd::MethodDef { RVA: 0, @@ -117,13 +161,19 @@ fn write_interface(writer: &mut winmd::Writer, namespace: &str, name: &str, memb }); for (sequence, param) in signature.params.iter().enumerate() { - writer.tables.Param.push(winmd::Param { Flags: 0, Sequence: (sequence + 1) as u16, Name: writer.strings.insert(¶m.name) }); + writer.tables.Param.push(winmd::Param { + Flags: 0, + Sequence: (sequence + 1) as u16, + Name: writer.strings.insert(¶m.name), + }); } } } fn write_struct(writer: &mut winmd::Writer, namespace: &str, name: &str, member: &Struct) { - let mut flags = metadata::TypeAttributes::Public | metadata::TypeAttributes::Sealed | metadata::TypeAttributes::SequentialLayout; + let mut flags = metadata::TypeAttributes::Public + | metadata::TypeAttributes::Sealed + | metadata::TypeAttributes::SequentialLayout; if member.winrt { flags |= metadata::TypeAttributes::WindowsRuntime @@ -145,14 +195,20 @@ fn write_struct(writer: &mut winmd::Writer, namespace: &str, name: &str, member: let ty = syn_type(namespace, &[], &field.ty); let signature = writer.insert_field_sig(&ty); - writer.tables.Field.push(winmd::Field { Flags: flags.0, Name: writer.strings.insert(&field.name), Signature: signature }); + writer.tables.Field.push(winmd::Field { + Flags: flags.0, + Name: writer.strings.insert(&field.name), + Signature: signature, + }); } } fn write_enum(_writer: &mut winmd::Writer, _namespace: &str, _name: &str, _member: &Enum) {} fn write_class(writer: &mut winmd::Writer, namespace: &str, name: &str, member: &Class) { - let flags = metadata::TypeAttributes::Public | metadata::TypeAttributes::Sealed | metadata::TypeAttributes::WindowsRuntime; + let flags = metadata::TypeAttributes::Public + | metadata::TypeAttributes::Sealed + | metadata::TypeAttributes::WindowsRuntime; let extends = if let Some(base) = &member.base { match syn_type_path(namespace, &[], base) { @@ -177,14 +233,21 @@ fn write_class(writer: &mut winmd::Writer, namespace: &str, name: &str, member: let ty = syn_type_path(namespace, &[], extends); let reference = match &ty { - winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => writer.insert_type_ref(&type_name.namespace, &type_name.name), + winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => { + writer.insert_type_ref(&type_name.namespace, &type_name.name) + } winmd::Type::TypeRef(_) => writer.insert_type_spec(ty), winmd::Type::IUnknown => writer.insert_type_ref("Windows.Win32.System.Com", "IUnknown"), - winmd::Type::IInspectable => writer.insert_type_ref("Windows.Win32.System.WinRT", "IInspectable"), + winmd::Type::IInspectable => { + writer.insert_type_ref("Windows.Win32.System.WinRT", "IInspectable") + } rest => unimplemented!("{rest:?}"), }; - writer.tables.InterfaceImpl.push(writer::InterfaceImpl { Class: writer.tables.TypeDef.len() as u32 - 1, Interface: reference }); + writer.tables.InterfaceImpl.push(writer::InterfaceImpl { + Class: writer.tables.TypeDef.len() as u32 - 1, + Interface: reference, + }); if index == 0 { // TODO: add the DefaultAttribute to the first interface @@ -209,9 +272,17 @@ fn syn_signature(namespace: &str, generics: &[String], sig: &syn::Signature) -> }) .collect(); - let return_type = if let syn::ReturnType::Type(_, ty) = &sig.output { syn_type(namespace, generics, ty) } else { winmd::Type::Void }; + let return_type = if let syn::ReturnType::Type(_, ty) = &sig.output { + syn_type(namespace, generics, ty) + } else { + winmd::Type::Void + }; - winmd::Signature { params, return_type, call_flags: 0 } + winmd::Signature { + params, + return_type, + call_flags: 0, + } } fn syn_type(namespace: &str, generics: &[String], ty: &syn::Type) -> winmd::Type { @@ -316,19 +387,29 @@ fn syn_path(namespace: &str, generics: &[String], path: &syn::Path) -> winmd::Ty // Unwrapping is fine as there should always be at least one segment. let (name, type_namespace) = builder.split_last().unwrap(); - let type_namespace = if type_namespace.is_empty() { namespace.to_string() } else { type_namespace.join(".") }; + let type_namespace = if type_namespace.is_empty() { + namespace.to_string() + } else { + type_namespace.join(".") + }; let mut type_generics = vec![]; if let Some(segment) = path.segments.last() { if let syn::PathArguments::AngleBracketed(args) = &segment.arguments { for arg in &args.args { match arg { - syn::GenericArgument::Type(ty) => type_generics.push(syn_type(namespace, generics, ty)), + syn::GenericArgument::Type(ty) => { + type_generics.push(syn_type(namespace, generics, ty)) + } rest => unimplemented!("{rest:?}"), } } } } - winmd::Type::TypeRef(winmd::TypeName { namespace: type_namespace, name: name.to_string(), generics: type_generics }) + winmd::Type::TypeRef(winmd::TypeName { + namespace: type_namespace, + name: name.to_string(), + generics: type_generics, + }) } diff --git a/crates/libs/bindgen/src/rust/cfg.rs b/crates/libs/bindgen/src/rust/cfg.rs index b323fb8e3d..40e94795da 100644 --- a/crates/libs/bindgen/src/rust/cfg.rs +++ b/crates/libs/bindgen/src/rust/cfg.rs @@ -3,7 +3,8 @@ use metadata::{AsRow, HasAttributes}; #[derive(Default, Clone)] pub struct Cfg { - pub types: std::collections::BTreeMap<&'static str, std::collections::BTreeSet>, + pub types: + std::collections::BTreeMap<&'static str, std::collections::BTreeSet>, pub core_types: std::collections::BTreeSet, pub arches: std::collections::BTreeSet<&'static str>, pub deprecated: bool, @@ -38,7 +39,12 @@ pub fn field_cfg(writer: &Writer, row: metadata::Field) -> Cfg { field_cfg_combine(writer, row, None, &mut cfg); cfg } -fn field_cfg_combine(writer: &Writer, row: metadata::Field, enclosing: Option, cfg: &mut Cfg) { +fn field_cfg_combine( + writer: &Writer, + row: metadata::Field, + enclosing: Option, + cfg: &mut Cfg, +) { type_cfg_combine(writer, &row.ty(enclosing), cfg) } @@ -48,10 +54,19 @@ pub fn type_def_cfg(writer: &Writer, row: metadata::TypeDef, generics: &[metadat cfg_add_attributes(&mut cfg, row); cfg } -pub fn type_def_cfg_impl(writer: &Writer, def: metadata::TypeDef, generics: &[metadata::Type]) -> Cfg { +pub fn type_def_cfg_impl( + writer: &Writer, + def: metadata::TypeDef, + generics: &[metadata::Type], +) -> Cfg { let mut cfg = Cfg::default(); - fn combine(writer: &Writer, def: metadata::TypeDef, generics: &[metadata::Type], cfg: &mut Cfg) { + fn combine( + writer: &Writer, + def: metadata::TypeDef, + generics: &[metadata::Type], + cfg: &mut Cfg, + ) { type_def_cfg_combine(writer, def, generics, cfg); for method in def.methods() { @@ -70,7 +85,12 @@ pub fn type_def_cfg_impl(writer: &Writer, def: metadata::TypeDef, generics: &[me cfg_add_attributes(&mut cfg, def); cfg } -pub fn type_def_cfg_combine(writer: &Writer, row: metadata::TypeDef, generics: &[metadata::Type], cfg: &mut Cfg) { +pub fn type_def_cfg_combine( + writer: &Writer, + row: metadata::TypeDef, + generics: &[metadata::Type], + cfg: &mut Cfg, +) { let type_kind = row.kind(); if writer.sys && type_kind == metadata::TypeKind::Interface { @@ -83,7 +103,12 @@ pub fn type_def_cfg_combine(writer: &Writer, row: metadata::TypeDef, generics: & type_cfg_combine(writer, generic, cfg); } - if cfg.types.entry(type_name.namespace()).or_default().insert(row) { + if cfg + .types + .entry(type_name.namespace()) + .or_default() + .insert(row) + { match type_kind { metadata::TypeKind::Class => { if let Some(default_interface) = metadata::type_def_default_interface(row) { @@ -91,7 +116,10 @@ pub fn type_def_cfg_combine(writer: &Writer, row: metadata::TypeDef, generics: & } } metadata::TypeKind::Interface => { - if !row.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + if !row + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { for def in metadata::type_def_vtables(row) { if let metadata::Type::TypeDef(def, _) = def { cfg.add_feature(def.namespace()); @@ -100,16 +128,24 @@ pub fn type_def_cfg_combine(writer: &Writer, row: metadata::TypeDef, generics: & } } metadata::TypeKind::Struct => { - row.fields().for_each(|field| field_cfg_combine(writer, field, Some(row), cfg)); + row.fields() + .for_each(|field| field_cfg_combine(writer, field, Some(row), cfg)); if !type_name.namespace().is_empty() { - for def in row.reader().get_type_def(type_name.namespace(), type_name.name()) { + for def in row + .reader() + .get_type_def(type_name.namespace(), type_name.name()) + { if def != row { type_def_cfg_combine(writer, def, &[], cfg); } } } } - metadata::TypeKind::Delegate => signature_cfg_combine(writer, &metadata::type_def_invoke_method(row).signature(generics), cfg), + metadata::TypeKind::Delegate => signature_cfg_combine( + writer, + &metadata::type_def_invoke_method(row).signature(generics), + cfg, + ), _ => {} } } @@ -123,7 +159,10 @@ pub fn signature_cfg(writer: &Writer, method: metadata::MethodDef) -> Cfg { } fn signature_cfg_combine(writer: &Writer, signature: &metadata::MethodDefSig, cfg: &mut Cfg) { type_cfg_combine(writer, &signature.return_type, cfg); - signature.params.iter().for_each(|param| type_cfg_combine(writer, param, cfg)); + signature + .params + .iter() + .for_each(|param| type_cfg_combine(writer, param, cfg)); } fn cfg_add_attributes>(cfg: &mut Cfg, row: R) { diff --git a/crates/libs/bindgen/src/rust/classes.rs b/crates/libs/bindgen/src/rust/classes.rs index 753f4f76f0..0a3287f47f 100644 --- a/crates/libs/bindgen/src/rust/classes.rs +++ b/crates/libs/bindgen/src/rust/classes.rs @@ -2,7 +2,10 @@ use super::*; use metadata::HasAttributes; pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { - if !def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + if !def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { return quote! {}; } @@ -38,7 +41,15 @@ fn gen_class(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let mut virtual_names = MethodNames::new(); for method in def.methods() { - methods.combine(&winrt_methods::writer(writer, *def, generics, interface.kind, method, &mut method_names, &mut virtual_names)); + methods.combine(&winrt_methods::writer( + writer, + *def, + generics, + interface.kind, + method, + &mut method_names, + &mut virtual_names, + )); } } } @@ -104,11 +115,40 @@ fn gen_class(writer: &Writer, def: metadata::TypeDef) -> TokenStream { } }); - tokens.combine(&writer.interface_winrt_trait(def, &[], &name, &TokenStream::new(), &TokenStream::new(), &features)); - tokens.combine(&writer.interface_trait(def, &[], &name, &TokenStream::new(), &features, true)); + tokens.combine(&writer.interface_winrt_trait( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&writer.interface_trait( + def, + &[], + &name, + &TokenStream::new(), + &features, + true, + )); tokens.combine(&writer.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); - tokens.combine(&writer.async_get(def, &[], &name, &TokenStream::new(), &TokenStream::new(), &features)); - tokens.combine(&iterators::writer(writer, def, &[], &name, &TokenStream::new(), &TokenStream::new(), &cfg)); + tokens.combine(&writer.async_get( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&iterators::writer( + writer, + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &cfg, + )); tokens.combine(&writer.agile(def, &name, &TokenStream::new(), &features)); tokens } else { @@ -127,7 +167,13 @@ fn gen_class(writer: &Writer, def: metadata::TypeDef) -> TokenStream { } } -fn gen_conversions(writer: &Writer, def: metadata::TypeDef, ident: &TokenStream, interfaces: &[metadata::Interface], cfg: &cfg::Cfg) -> TokenStream { +fn gen_conversions( + writer: &Writer, + def: metadata::TypeDef, + ident: &TokenStream, + interfaces: &[metadata::Interface], + cfg: &cfg::Cfg, +) -> TokenStream { let features = writer.cfg_features(cfg); let mut tokens = quote! { #features @@ -143,7 +189,10 @@ fn gen_conversions(writer: &Writer, def: metadata::TypeDef, ident: &TokenStream, continue; } - if interface.kind != metadata::InterfaceKind::Default && interface.kind != metadata::InterfaceKind::None && interface.kind != metadata::InterfaceKind::Base { + if interface.kind != metadata::InterfaceKind::Default + && interface.kind != metadata::InterfaceKind::None + && interface.kind != metadata::InterfaceKind::Base + { continue; } @@ -172,7 +221,11 @@ fn gen_conversions(writer: &Writer, def: metadata::TypeDef, ident: &TokenStream, fn type_def_has_default_constructor(row: metadata::TypeDef) -> bool { for attribute in row.attributes() { if attribute.name() == "ActivatableAttribute" { - if attribute.args().iter().any(|arg| matches!(arg.1, metadata::Value::TypeName(_))) { + if attribute + .args() + .iter() + .any(|arg| matches!(arg.1, metadata::Value::TypeName(_))) + { continue; } else { return true; diff --git a/crates/libs/bindgen/src/rust/com_methods.rs b/crates/libs/bindgen/src/rust/com_methods.rs index fa6b3aebed..ffd85d3fa6 100644 --- a/crates/libs/bindgen/src/rust/com_methods.rs +++ b/crates/libs/bindgen/src/rust/com_methods.rs @@ -1,6 +1,13 @@ use super::*; -pub fn writer(writer: &Writer, def: metadata::TypeDef, kind: metadata::InterfaceKind, method: metadata::MethodDef, method_names: &mut MethodNames, virtual_names: &mut MethodNames) -> TokenStream { +pub fn writer( + writer: &Writer, + def: metadata::TypeDef, + kind: metadata::InterfaceKind, + method: metadata::MethodDef, + method_names: &mut MethodNames, + virtual_names: &mut MethodNames, +) -> TokenStream { let signature = metadata::method_def_signature(def.namespace(), method, &[]); let name = method_names.add(method); @@ -26,7 +33,8 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, kind: metadata::Interface let args = writer.win32_args(&signature.params, kind); let params = writer.win32_params(&signature.params, kind); let generics = expand_generics(generics, quote!(T)); - let where_clause = expand_where_clause(where_clause, quote!(T: windows_core::Interface)); + let where_clause = + expand_where_clause(where_clause, quote!(T: windows_core::Interface)); quote! { #features @@ -40,7 +48,8 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, kind: metadata::Interface let args = writer.win32_args(&signature.params, kind); let params = writer.win32_params(&signature.params, kind); let generics = expand_generics(generics, quote!(T)); - let where_clause = expand_where_clause(where_clause, quote!(T: windows_core::Interface)); + let where_clause = + expand_where_clause(where_clause, quote!(T: windows_core::Interface)); quote! { #features @@ -160,7 +169,9 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, kind: metadata::Interface pub fn gen_upcall(writer: &Writer, sig: &metadata::Signature, inner: TokenStream) -> TokenStream { match sig.kind() { metadata::SignatureKind::ResultValue => { - let invoke_args = sig.params[..sig.params.len() - 1].iter().map(|param| gen_win32_invoke_arg(writer, param)); + let invoke_args = sig.params[..sig.params.len() - 1] + .iter() + .map(|param| gen_win32_invoke_arg(writer, param)); let result = writer.param_name(sig.params[sig.params.len() - 1].def); @@ -175,22 +186,33 @@ pub fn gen_upcall(writer: &Writer, sig: &metadata::Signature, inner: TokenStream } } } - metadata::SignatureKind::Query(_) | metadata::SignatureKind::QueryOptional(_) | metadata::SignatureKind::ResultVoid => { - let invoke_args = sig.params.iter().map(|param| gen_win32_invoke_arg(writer, param)); + metadata::SignatureKind::Query(_) + | metadata::SignatureKind::QueryOptional(_) + | metadata::SignatureKind::ResultVoid => { + let invoke_args = sig + .params + .iter() + .map(|param| gen_win32_invoke_arg(writer, param)); quote! { #inner(this, #(#invoke_args,)*).into() } } metadata::SignatureKind::ReturnStruct => { - let invoke_args = sig.params.iter().map(|param| gen_win32_invoke_arg(writer, param)); + let invoke_args = sig + .params + .iter() + .map(|param| gen_win32_invoke_arg(writer, param)); quote! { *result__ = #inner(this, #(#invoke_args,)*) } } _ => { - let invoke_args = sig.params.iter().map(|param| gen_win32_invoke_arg(writer, param)); + let invoke_args = sig + .params + .iter() + .map(|param| gen_win32_invoke_arg(writer, param)); quote! { #inner(this, #(#invoke_args,)*) @@ -202,9 +224,14 @@ pub fn gen_upcall(writer: &Writer, sig: &metadata::Signature, inner: TokenStream fn gen_win32_invoke_arg(writer: &Writer, param: &metadata::SignatureParam) -> TokenStream { let name = writer.param_name(param.def); - if param.def.flags().contains(metadata::ParamAttributes::In) && metadata::type_is_nullable(¶m.ty) { + if param.def.flags().contains(metadata::ParamAttributes::In) + && metadata::type_is_nullable(¶m.ty) + { quote! { windows_core::from_raw_borrowed(&#name) } - } else if (!param.ty.is_pointer() && metadata::type_is_nullable(¶m.ty)) || (param.def.flags().contains(metadata::ParamAttributes::In) && !metadata::type_is_primitive(¶m.ty)) { + } else if (!param.ty.is_pointer() && metadata::type_is_nullable(¶m.ty)) + || (param.def.flags().contains(metadata::ParamAttributes::In) + && !metadata::type_is_primitive(¶m.ty)) + { quote! { core::mem::transmute(&#name) } } else { quote! { core::mem::transmute_copy(&#name) } diff --git a/crates/libs/bindgen/src/rust/constants.rs b/crates/libs/bindgen/src/rust/constants.rs index 9f54e99690..5f8520cd3d 100644 --- a/crates/libs/bindgen/src/rust/constants.rs +++ b/crates/libs/bindgen/src/rust/constants.rs @@ -105,7 +105,11 @@ fn initializer(writer: &Writer, def: metadata::Field) -> Option { Some(result) } -fn field_initializer<'a>(writer: &Writer, field: metadata::Field, input: &'a str) -> (TokenStream, &'a str) { +fn field_initializer<'a>( + writer: &Writer, + field: metadata::Field, + input: &'a str, +) -> (TokenStream, &'a str) { let name = to_ident(field.name()); match field.ty(None) { @@ -191,7 +195,8 @@ fn read_literal_array(input: &str, len: usize) -> (Vec<&str>, &str) { } fn field_guid(row: metadata::Field) -> Option { - row.find_attribute("GuidAttribute").map(|attribute| metadata::Guid::from_args(&attribute.args())) + row.find_attribute("GuidAttribute") + .map(|attribute| metadata::Guid::from_args(&attribute.args())) } fn field_is_ansi(row: metadata::Field) -> bool { @@ -200,8 +205,12 @@ fn field_is_ansi(row: metadata::Field) -> bool { fn type_has_replacement(ty: &metadata::Type) -> bool { match ty { - metadata::Type::Name(metadata::TypeName::HResult) | metadata::Type::Const(metadata::TypeName::PSTR) | metadata::Type::Const(metadata::TypeName::PWSTR) => true, - metadata::Type::TypeDef(row, _) => metadata::type_def_is_handle(*row) || row.kind() == metadata::TypeKind::Enum, + metadata::Type::Name(metadata::TypeName::HResult) + | metadata::Type::Const(metadata::TypeName::PSTR) + | metadata::Type::Const(metadata::TypeName::PWSTR) => true, + metadata::Type::TypeDef(row, _) => { + metadata::type_def_is_handle(*row) || row.kind() == metadata::TypeKind::Enum + } _ => false, } } diff --git a/crates/libs/bindgen/src/rust/delegates.rs b/crates/libs/bindgen/src/rust/delegates.rs index 939215754f..01f094cd2b 100644 --- a/crates/libs/bindgen/src/rust/delegates.rs +++ b/crates/libs/bindgen/src/rust/delegates.rs @@ -1,7 +1,10 @@ use super::*; pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { gen_delegate(writer, def) } else { gen_callback(writer, def) @@ -67,8 +70,17 @@ fn gen_win_delegate(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let features = writer.cfg_features(&cfg); let vtbl_signature = writer.vtbl_signature(def, true, &signature); - let invoke = winrt_methods::writer(writer, def, generics, metadata::InterfaceKind::Default, method, &mut MethodNames::new(), &mut MethodNames::new()); - let invoke_upcall = winrt_methods::gen_upcall(writer, &signature, quote! { (this.invoke) }, false); + let invoke = winrt_methods::writer( + writer, + def, + generics, + metadata::InterfaceKind::Default, + method, + &mut MethodNames::new(), + &mut MethodNames::new(), + ); + let invoke_upcall = + winrt_methods::gen_upcall(writer, &signature, quote! { (this.invoke) }, false); let mut tokens = if generics.is_empty() { let iid = writer.guid_literal(metadata::type_def_guid(def)); @@ -160,12 +172,23 @@ fn gen_win_delegate(writer: &Writer, def: metadata::TypeDef) -> TokenStream { }); tokens.combine(&writer.interface_trait(def, generics, &ident, &constraints, &features, true)); - tokens.combine(&writer.interface_winrt_trait(def, generics, &ident, &constraints, &phantoms, &features)); + tokens.combine(&writer.interface_winrt_trait( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); tokens.combine(&writer.interface_vtbl(def, generics, &constraints, &features)); tokens } -fn gen_fn_constraint(writer: &Writer, def: metadata::TypeDef, signature: &metadata::Signature) -> TokenStream { +fn gen_fn_constraint( + writer: &Writer, + def: metadata::TypeDef, + signature: &metadata::Signature, +) -> TokenStream { let signature = writer.impl_signature(def, signature); quote! { F: FnMut #signature + Send + 'static } diff --git a/crates/libs/bindgen/src/rust/enums.rs b/crates/libs/bindgen/src/rust/enums.rs index a8074d4e94..59ec5666a4 100644 --- a/crates/libs/bindgen/src/rust/enums.rs +++ b/crates/libs/bindgen/src/rust/enums.rs @@ -8,7 +8,10 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let underlying_type = writer.type_name(&underlying_type); // TODO: unscoped enums should be removed from metadata - let is_scoped = def.flags().contains(metadata::TypeAttributes::WindowsRuntime) || def.has_attribute("ScopedEnumAttribute"); + let is_scoped = def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + || def.has_attribute("ScopedEnumAttribute"); let cfg = cfg::type_def_cfg(writer, def, &[]); let features = writer.cfg_features(&cfg); @@ -89,7 +92,11 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { // Win32 enums use the Flags attribute. WinRT enums don't have the Flags attribute but are paritioned merely based // on whether they are signed. // TODO: Win32 metadata should just follow WinRT's example here. - let type_def_is_flags = def.has_attribute("FlagsAttribute") || (def.flags().contains(metadata::TypeAttributes::WindowsRuntime) && def.underlying_type() == metadata::Type::U32); + let type_def_is_flags = def.has_attribute("FlagsAttribute") + || (def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + && def.underlying_type() == metadata::Type::U32); if type_def_is_flags { tokens.combine("e! { @@ -138,7 +145,10 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { }); } - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { let signature = Literal::byte_string(metadata::type_def_signature(def, &[]).as_bytes()); tokens.combine("e! { diff --git a/crates/libs/bindgen/src/rust/extensions/mod.rs b/crates/libs/bindgen/src/rust/extensions/mod.rs index 45be29f15f..3a42b9b452 100644 --- a/crates/libs/bindgen/src/rust/extensions/mod.rs +++ b/crates/libs/bindgen/src/rust/extensions/mod.rs @@ -10,10 +10,28 @@ pub fn gen_mod(writer: &Writer, namespace: &str) -> TokenStream { } 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.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/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.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.System.Rpc" => include_str!("mod/Win32/System/Rpc/RPC_STATUS.rs"), "Windows.Win32.System.Com" => include_str!("mod/Win32/System/Com/IDispatch.rs"), "Windows.Win32.UI.WindowsAndMessaging" => { @@ -26,7 +44,11 @@ pub fn gen_mod(writer: &Writer, namespace: &str) -> TokenStream { 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"),), + "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/crates/libs/bindgen/src/rust/functions.rs b/crates/libs/bindgen/src/rust/functions.rs index 8af4d6ae33..1cd841c4c6 100644 --- a/crates/libs/bindgen/src/rust/functions.rs +++ b/crates/libs/bindgen/src/rust/functions.rs @@ -50,7 +50,8 @@ fn gen_win_function(writer: &Writer, namespace: &str, def: metadata::MethodDef) let args = writer.win32_args(&signature.params, kind); let params = writer.win32_params(&signature.params, kind); let generics = expand_generics(generics, quote!(T)); - let where_clause = expand_where_clause(where_clause, quote!(T: windows_core::Interface)); + let where_clause = + expand_where_clause(where_clause, quote!(T: windows_core::Interface)); quote! { #features @@ -66,7 +67,8 @@ fn gen_win_function(writer: &Writer, namespace: &str, def: metadata::MethodDef) let args = writer.win32_args(&signature.params, kind); let params = writer.win32_params(&signature.params, kind); let generics = expand_generics(generics, quote!(T)); - let where_clause = expand_where_clause(where_clause, quote!(T: windows_core::Interface)); + let where_clause = + expand_where_clause(where_clause, quote!(T: windows_core::Interface)); quote! { #features @@ -204,11 +206,19 @@ fn gen_link(writer: &Writer, namespace: &str, signature: &metadata::Signature) - let ident = to_ident(name); // Windows libs are always produced with lowercase module names. - let library = if namespace.starts_with("Windows.") { signature.def.module_name().to_lowercase() } else { signature.def.module_name().to_string() }; + let library = if namespace.starts_with("Windows.") { + signature.def.module_name().to_lowercase() + } else { + signature.def.module_name().to_string() + }; let abi = method_def_extern_abi(signature.def); - let symbol = if let Some(impl_map) = signature.def.impl_map() { impl_map.import_name() } else { name }; + let symbol = if let Some(impl_map) = signature.def.impl_map() { + impl_map.import_name() + } else { + name + }; let link_name = if symbol != name { quote! { #[link_name = #symbol] } @@ -218,13 +228,21 @@ fn gen_link(writer: &Writer, namespace: &str, signature: &metadata::Signature) - let params = signature.params.iter().map(|p| { let name = writer.param_name(p.def); - let tokens = if p.kind == metadata::SignatureParamKind::ValueType { writer.type_default_name(&p.ty) } else { writer.type_abi_name(&p.ty) }; + let tokens = if p.kind == metadata::SignatureParamKind::ValueType { + writer.type_default_name(&p.ty) + } else { + writer.type_abi_name(&p.ty) + }; quote! { #name: #tokens } }); let return_type = writer.return_sig(signature); - let vararg = if writer.sys && signature.call_flags.contains(metadata::MethodCallAttributes::VARARG) { + let vararg = if writer.sys + && signature + .call_flags + .contains(metadata::MethodCallAttributes::VARARG) + { "...".into() } else { quote! {} @@ -241,7 +259,11 @@ fn gen_link(writer: &Writer, namespace: &str, signature: &metadata::Signature) - } } } else { - let symbol = if symbol != name { format!(" \"{symbol}\"") } else { String::new() }; + let symbol = if symbol != name { + format!(" \"{symbol}\"") + } else { + String::new() + }; let mut tokens = String::new(); for param in params { @@ -263,7 +285,10 @@ fn does_not_return(def: metadata::MethodDef) -> TokenStream { fn handle_last_error(def: metadata::MethodDef, signature: &metadata::Signature) -> bool { if let Some(map) = def.impl_map() { - if map.flags().contains(metadata::PInvokeAttributes::SupportsLastError) { + if map + .flags() + .contains(metadata::PInvokeAttributes::SupportsLastError) + { if let metadata::Type::TypeDef(return_type, _) = &signature.return_type { if metadata::type_def_is_handle(*return_type) { // https://github.com/microsoft/windows-rs/issues/2392#issuecomment-1477765781 diff --git a/crates/libs/bindgen/src/rust/handles.rs b/crates/libs/bindgen/src/rust/handles.rs index 844fff0dbe..2cadef958a 100644 --- a/crates/libs/bindgen/src/rust/handles.rs +++ b/crates/libs/bindgen/src/rust/handles.rs @@ -135,7 +135,10 @@ pub fn gen_win_handle(writer: &Writer, def: metadata::TypeDef) -> TokenStream { fn type_def_usable_for(row: metadata::TypeDef) -> Option { if let Some(attribute) = row.find_attribute("AlsoUsableForAttribute") { if let Some((_, metadata::Value::String(name))) = attribute.args().first() { - return row.reader().get_type_def(row.namespace(), name.as_str()).next(); + return row + .reader() + .get_type_def(row.namespace(), name.as_str()) + .next(); } } None @@ -149,7 +152,11 @@ fn free_function(def: metadata::TypeDef) -> Option { } if let Some((_, metadata::Value::String(name))) = attribute.args().first() { - if let Some((method, _)) = def.reader().get_method_def(def.namespace(), name.as_str()).next() { + if let Some((method, _)) = def + .reader() + .get_method_def(def.namespace(), name.as_str()) + .next() + { return Some(method); } } diff --git a/crates/libs/bindgen/src/rust/implements.rs b/crates/libs/bindgen/src/rust/implements.rs index d77ed196b5..cccf8503a2 100644 --- a/crates/libs/bindgen/src/rust/implements.rs +++ b/crates/libs/bindgen/src/rust/implements.rs @@ -2,7 +2,9 @@ use super::*; use metadata::HasAttributes; pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { - if def.kind() != metadata::TypeKind::Interface || (!writer.implement && def.has_attribute("ExclusiveToAttribute")) { + if def.kind() != metadata::TypeKind::Interface + || (!writer.implement && def.has_attribute("ExclusiveToAttribute")) + { return quote! {}; } @@ -24,9 +26,16 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let mut requires = quote! {}; let type_ident = quote! { #type_ident<#generic_names> }; let vtables = metadata::type_def_vtables(def); - let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::Name(metadata::TypeName::IUnknown))); - - fn gen_required_trait(writer: &Writer, def: metadata::TypeDef, generics: &[metadata::Type]) -> TokenStream { + let has_unknown_base = matches!( + vtables.first(), + Some(metadata::Type::Name(metadata::TypeName::IUnknown)) + ); + + fn gen_required_trait( + writer: &Writer, + def: metadata::TypeDef, + generics: &[metadata::Type], + ) -> TokenStream { let name = writer.type_def_name_imp(def, generics, "_Impl"); quote! { + #name @@ -49,16 +58,21 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { } } - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { // TODO: this awkward wrapping of TypeDefs needs fixing - for interface in metadata::type_interfaces(&metadata::Type::TypeDef(def, generics.to_vec())) { + for interface in metadata::type_interfaces(&metadata::Type::TypeDef(def, generics.to_vec())) + { if let metadata::Type::TypeDef(def, generics) = interface.ty { requires.combine(&gen_required_trait(writer, def, &generics)); } } } - let runtime_name = writer.runtime_name_trait(def, generics, &type_ident, &constraints, &features); + let runtime_name = + writer.runtime_name_trait(def, generics, &type_ident, &constraints, &features); let mut method_names = MethodNames::new(); diff --git a/crates/libs/bindgen/src/rust/index.rs b/crates/libs/bindgen/src/rust/index.rs index e0498f7941..8ea6b519fc 100644 --- a/crates/libs/bindgen/src/rust/index.rs +++ b/crates/libs/bindgen/src/rust/index.rs @@ -18,10 +18,16 @@ struct IndexItem { } pub fn gen_index(writer: &Writer) -> String { - let mut feature_index = Index { ..Default::default() }; + let mut feature_index = Index { + ..Default::default() + }; for namespace in writer.reader.namespaces() { - let namespace_idx = match feature_index.namespace_map.iter().position(|ns| ns == namespace) { + let namespace_idx = match feature_index + .namespace_map + .iter() + .position(|ns| ns == namespace) + { Some(idx) => idx, None => { feature_index.namespace_map.push(namespace.to_string()); @@ -30,7 +36,9 @@ pub fn gen_index(writer: &Writer) -> String { }; for item in writer.reader.namespace_items(namespace) { - let mut index_item = IndexItem { ..Default::default() }; + let mut index_item = IndexItem { + ..Default::default() + }; let mut cfg = Cfg::default(); cfg.add_feature(namespace); @@ -52,16 +60,22 @@ pub fn gen_index(writer: &Writer) -> String { let cfg_features = cfg_features(&cfg); index_item.features = cfg_features .iter() - .map(|feature| match feature_index.feature_map.iter().position(|f| f == feature) { - Some(idx) => idx, - None => { - feature_index.feature_map.push(feature.to_string()); - feature_index.feature_map.len() - 1 - } - }) + .map( + |feature| match feature_index.feature_map.iter().position(|f| f == feature) { + Some(idx) => idx, + None => { + feature_index.feature_map.push(feature.to_string()); + feature_index.feature_map.len() - 1 + } + }, + ) .collect(); - feature_index.namespaces.entry(namespace_idx).or_default().push(index_item); + feature_index + .namespaces + .entry(namespace_idx) + .or_default() + .push(index_item); } } diff --git a/crates/libs/bindgen/src/rust/interfaces.rs b/crates/libs/bindgen/src/rust/interfaces.rs index 9f35000980..c89b454f30 100644 --- a/crates/libs/bindgen/src/rust/interfaces.rs +++ b/crates/libs/bindgen/src/rust/interfaces.rs @@ -14,7 +14,10 @@ fn gen_sys_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream { } let vtables = metadata::type_def_vtables(def); - let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::Name(metadata::TypeName::IUnknown))); + let has_unknown_base = matches!( + vtables.first(), + Some(metadata::Type::Name(metadata::TypeName::IUnknown)) + ); let mut tokens = quote! {}; @@ -42,7 +45,10 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let features = writer.cfg_features(&cfg); let interfaces = metadata::type_interfaces(&metadata::Type::TypeDef(def, generics.to_vec())); let vtables = metadata::type_def_vtables(def); - let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::Name(metadata::TypeName::IUnknown))); + let has_unknown_base = matches!( + vtables.first(), + Some(metadata::Type::Name(metadata::TypeName::IUnknown)) + ); let mut tokens = quote! {}; @@ -75,20 +81,46 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let method_names = &mut MethodNames::new(); let virtual_names = &mut MethodNames::new(); - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { for method in def.methods() { - methods.combine(&winrt_methods::writer(writer, def, generics, metadata::InterfaceKind::Default, method, method_names, virtual_names)); + methods.combine(&winrt_methods::writer( + writer, + def, + generics, + metadata::InterfaceKind::Default, + method, + method_names, + virtual_names, + )); } for interface in &interfaces { if let metadata::Type::TypeDef(def, generics) = &interface.ty { for method in def.methods() { - methods.combine(&winrt_methods::writer(writer, *def, generics, metadata::InterfaceKind::None, method, method_names, virtual_names)); + methods.combine(&winrt_methods::writer( + writer, + *def, + generics, + metadata::InterfaceKind::None, + method, + method_names, + virtual_names, + )); } } } } else { for method in def.methods() { - methods.combine(&com_methods::writer(writer, def, metadata::InterfaceKind::Default, method, method_names, virtual_names)); + methods.combine(&com_methods::writer( + writer, + def, + metadata::InterfaceKind::Default, + method, + method_names, + virtual_names, + )); } } @@ -131,7 +163,11 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream { } } - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) && !interfaces.is_empty() { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + && !interfaces.is_empty() + { if generics.is_empty() { let mut hierarchy = format!("windows_core::imp::required_hierarchy!({ident}"); let mut hierarchy_cfg = cfg.clone(); @@ -165,13 +201,42 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream { } }); - tokens.combine(&writer.async_get(def, generics, &ident, &constraints, &phantoms, &features)); - tokens.combine(&iterators::writer(writer, def, generics, &ident, &constraints, &phantoms, &cfg)); + tokens.combine(&writer.async_get( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&iterators::writer( + writer, + def, + generics, + &ident, + &constraints, + &phantoms, + &cfg, + )); tokens.combine(&writer.agile(def, &ident, &constraints, &features)); } - tokens.combine(&writer.interface_winrt_trait(def, generics, &ident, &constraints, &phantoms, &features)); - tokens.combine(&writer.interface_trait(def, generics, &ident, &constraints, &features, has_unknown_base)); + tokens.combine(&writer.interface_winrt_trait( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&writer.interface_trait( + def, + generics, + &ident, + &constraints, + &features, + has_unknown_base, + )); tokens.combine(&writer.interface_vtbl(def, generics, &constraints, &features)); tokens } diff --git a/crates/libs/bindgen/src/rust/iterators.rs b/crates/libs/bindgen/src/rust/iterators.rs index 571489023d..145a29ea93 100644 --- a/crates/libs/bindgen/src/rust/iterators.rs +++ b/crates/libs/bindgen/src/rust/iterators.rs @@ -1,6 +1,14 @@ use super::*; -pub fn writer(writer: &Writer, def: metadata::TypeDef, generics: &[metadata::Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, cfg: &cfg::Cfg) -> TokenStream { +pub fn writer( + writer: &Writer, + def: metadata::TypeDef, + generics: &[metadata::Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + cfg: &cfg::Cfg, +) -> TokenStream { match def.type_name() { // If the type is IIterator then simply implement the Iterator trait over top. metadata::TypeName::IIterator => { diff --git a/crates/libs/bindgen/src/rust/method_names.rs b/crates/libs/bindgen/src/rust/method_names.rs index ff6bf84d51..247fcd0630 100644 --- a/crates/libs/bindgen/src/rust/method_names.rs +++ b/crates/libs/bindgen/src/rust/method_names.rs @@ -22,7 +22,10 @@ impl MethodNames { fn method_def_special_name(row: metadata::MethodDef) -> String { let name = row.name(); - if row.flags().contains(metadata::MethodAttributes::SpecialName) { + if row + .flags() + .contains(metadata::MethodAttributes::SpecialName) + { if name.starts_with("get") { name[4..].to_string() } else if name.starts_with("put") { diff --git a/crates/libs/bindgen/src/rust/mod.rs b/crates/libs/bindgen/src/rust/mod.rs index 53792bcb22..6e6116bb56 100644 --- a/crates/libs/bindgen/src/rust/mod.rs +++ b/crates/libs/bindgen/src/rust/mod.rs @@ -23,7 +23,11 @@ use index::*; use rayon::prelude::*; use writer::*; -pub fn from_reader(reader: &'static metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { +pub fn from_reader( + reader: &'static metadata::Reader, + mut config: std::collections::BTreeMap<&str, &str>, + output: &str, +) -> Result<()> { let mut writer = Writer::new(reader, output); writer.package = config.remove("package").is_some(); writer.flatten = config.remove("flatten").is_some(); @@ -34,13 +38,22 @@ pub fn from_reader(reader: &'static metadata::Reader, mut config: std::collectio writer.no_inner_attributes = config.remove("no-inner-attributes").is_some(); writer.no_bindgen_comment = config.remove("no-bindgen-comment").is_some(); writer.vtbl = config.remove("vtbl").is_some(); + writer.rustfmt_config = if let Some(config) = config.remove("rustfmt-config") { + config.to_string() + } else { + String::new() + }; if writer.package && writer.flatten { - return Err(Error::new("cannot combine `package` and `flatten` configuration values")); + return Err(Error::new( + "cannot combine `package` and `flatten` configuration values", + )); } if writer.implement && writer.sys { - return Err(Error::new("cannot combine `implement` and `sys` configuration values")); + return Err(Error::new( + "cannot combine `implement` and `sys` configuration values", + )); } config.retain(|key, value| { @@ -103,7 +116,11 @@ fn gen_package(writer: &Writer) -> Result<()> { let directory = format!("{directory}/{}", tree.namespace.replace('.', "/")); let mut tokens = namespace(writer, tree); - let tokens_impl = if !writer.sys { namespace_impl(writer, tree) } else { String::new() }; + let tokens_impl = if !writer.sys { + namespace_impl(writer, tree) + } else { + String::new() + }; if !writer.sys && !tokens_impl.is_empty() { tokens.push_str("#[cfg(feature = \"implement\")]\ncore::include!(\"impl.rs\");\n"); @@ -140,7 +157,9 @@ fn gen_package(writer: &Writer) -> Result<()> { let dependency = &feature[..pos]; toml.push_str(&format!("{feature} = [\"{dependency}\"]\n")); - } else if tree.namespace.starts_with("Windows.Win32") || tree.namespace.starts_with("Windows.Wdk") { + } else if tree.namespace.starts_with("Windows.Win32") + || tree.namespace.starts_with("Windows.Wdk") + { toml.push_str(&format!("{feature} = [\"Win32_Foundation\"]\n")); } else if tree.namespace != "Windows.Foundation" { toml.push_str(&format!("{feature} = [\"Foundation\"]\n")); @@ -180,7 +199,10 @@ fn namespace(writer: &Writer, tree: &Tree) -> String { } let mut functions = std::collections::BTreeMap::<&str, TokenStream>::new(); - let mut types = std::collections::BTreeMap::>::new(); + let mut types = std::collections::BTreeMap::< + metadata::TypeKind, + std::collections::BTreeMap<&str, TokenStream>, + >::new(); for item in writer.reader.namespace_items(writer.namespace) { match item { @@ -192,15 +214,28 @@ fn namespace(writer: &Writer, tree: &Tree) -> String { if writer.reader.core_type(type_name).is_some() { continue; } - types.entry(def.kind()).or_default().entry(type_name.name()).or_default().combine(&writer.type_def(def)); + types + .entry(def.kind()) + .or_default() + .entry(type_name.name()) + .or_default() + .combine(&writer.type_def(def)); } metadata::Item::Fn(def, namespace) => { let name = def.name(); - functions.entry(name).or_default().combine(&functions::writer(writer, namespace, def)); + functions + .entry(name) + .or_default() + .combine(&functions::writer(writer, namespace, def)); } metadata::Item::Const(def) => { let name = def.name(); - types.entry(metadata::TypeKind::Class).or_default().entry(name).or_default().combine(&constants::writer(writer, def)); + types + .entry(metadata::TypeKind::Class) + .or_default() + .entry(name) + .or_default() + .combine(&constants::writer(writer, def)); } } } diff --git a/crates/libs/bindgen/src/rust/standalone.rs b/crates/libs/bindgen/src/rust/standalone.rs index c9d52c3e4f..bddc8e4465 100644 --- a/crates/libs/bindgen/src/rust/standalone.rs +++ b/crates/libs/bindgen/src/rust/standalone.rs @@ -87,7 +87,14 @@ pub fn standalone_imp(writer: &Writer) -> String { } for (function, namespace) in functions { - sorted.insert(&format!(".{}.{}", function.module_name().to_lowercase(), function.name()), functions::writer(writer, namespace, function)); + sorted.insert( + &format!( + ".{}.{}", + function.module_name().to_lowercase(), + function.name() + ), + functions::writer(writer, namespace, function), + ); } for constant in constants { @@ -108,19 +115,34 @@ impl SortedTokens { } } -fn item_collect_standalone(writer: &Writer, item: metadata::Item, set: &mut std::collections::BTreeSet) { +fn item_collect_standalone( + writer: &Writer, + item: metadata::Item, + set: &mut std::collections::BTreeSet, +) { match item { - metadata::Item::Type(def) => type_collect_standalone(writer, &metadata::Type::TypeDef(def, vec![]), set), - metadata::Item::Const(def) => type_collect_standalone(writer, &def.ty(None).to_const_type(), set), + metadata::Item::Type(def) => { + type_collect_standalone(writer, &metadata::Type::TypeDef(def, vec![]), set) + } + metadata::Item::Const(def) => { + type_collect_standalone(writer, &def.ty(None).to_const_type(), set) + } metadata::Item::Fn(def, namespace) => { let signature = metadata::method_def_signature(namespace, def, &[]); type_collect_standalone(writer, &signature.return_type, set); - signature.params.iter().for_each(|param| type_collect_standalone(writer, ¶m.ty, set)); + signature + .params + .iter() + .for_each(|param| type_collect_standalone(writer, ¶m.ty, set)); } } } // TODO: remove or move to riddle -fn type_collect_standalone(writer: &Writer, ty: &metadata::Type, set: &mut std::collections::BTreeSet) { +fn type_collect_standalone( + writer: &Writer, + ty: &metadata::Type, + set: &mut std::collections::BTreeSet, +) { let ty = ty.to_underlying_type(); if !set.insert(ty.clone()) { return; @@ -132,7 +154,11 @@ fn type_collect_standalone(writer: &Writer, ty: &metadata::Type, set: &mut std:: set.insert(metadata::Type::Name(metadata::TypeName::GUID)); set.insert(metadata::Type::Name(metadata::TypeName::HResult)); } - metadata::Type::Object => type_collect_standalone(writer, &metadata::Type::Name(metadata::TypeName::IUnknown), set), + metadata::Type::Object => type_collect_standalone( + writer, + &metadata::Type::Name(metadata::TypeName::IUnknown), + set, + ), _ => {} } } @@ -150,7 +176,10 @@ fn type_collect_standalone(writer: &Writer, ty: &metadata::Type, set: &mut std:: // by one architecture but not by another let type_name = def.type_name(); if !type_name.namespace().is_empty() { - for row in def.reader().get_type_def(type_name.namespace(), type_name.name()) { + for row in def + .reader() + .get_type_def(type_name.namespace(), type_name.name()) + { if def != row { type_collect_standalone(writer, &metadata::Type::TypeDef(row, Vec::new()), set); } @@ -178,7 +207,10 @@ fn type_collect_standalone(writer: &Writer, ty: &metadata::Type, set: &mut std:: } let signature = metadata::method_def_signature(def.namespace(), method, &generics); type_collect_standalone(writer, &signature.return_type, set); - signature.params.iter().for_each(|param| type_collect_standalone(writer, ¶m.ty, set)); + signature + .params + .iter() + .for_each(|param| type_collect_standalone(writer, ¶m.ty, set)); } for interface in metadata::type_interfaces(&ty) { @@ -192,7 +224,10 @@ fn type_collect_standalone(writer: &Writer, ty: &metadata::Type, set: &mut std:: } } metadata::TypeKind::Interface => { - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { type_collect_standalone(writer, &metadata::Type::Object, set); } } @@ -202,7 +237,11 @@ fn type_collect_standalone(writer: &Writer, ty: &metadata::Type, set: &mut std:: type_collect_standalone_nested(writer, def, set); } -fn type_collect_standalone_nested(writer: &Writer, td: metadata::TypeDef, set: &mut std::collections::BTreeSet) { +fn type_collect_standalone_nested( + writer: &Writer, + td: metadata::TypeDef, + set: &mut std::collections::BTreeSet, +) { for nested in td.reader().nested_types(td) { type_collect_standalone_nested(writer, nested, set); diff --git a/crates/libs/bindgen/src/rust/structs.rs b/crates/libs/bindgen/src/rust/structs.rs index 02c17fc5b4..40a02251c0 100644 --- a/crates/libs/bindgen/src/rust/structs.rs +++ b/crates/libs/bindgen/src/rust/structs.rs @@ -22,7 +22,12 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { gen_struct_with_name(writer, def, def.name(), &cfg::Cfg::default()) } -fn gen_struct_with_name(writer: &Writer, def: metadata::TypeDef, struct_name: &str, cfg: &cfg::Cfg) -> TokenStream { +fn gen_struct_with_name( + writer: &Writer, + def: metadata::TypeDef, + struct_name: &str, + cfg: &cfg::Cfg, +) -> TokenStream { let name = to_ident(struct_name); let flags = def.flags(); let cfg = cfg.union(cfg::type_def_cfg(writer, def, &[])); @@ -44,10 +49,16 @@ fn gen_struct_with_name(writer: &Writer, def: metadata::TypeDef, struct_name: &s if f.flags().contains(metadata::FieldAttributes::Literal) { quote! {} - } else if !writer.sys && flags.contains(metadata::TypeAttributes::ExplicitLayout) && !metadata::field_is_copyable(f, def) { + } else if !writer.sys + && flags.contains(metadata::TypeAttributes::ExplicitLayout) + && !metadata::field_is_copyable(f, def) + { let ty = writer.type_default_name(&ty); quote! { pub #name: core::mem::ManuallyDrop<#ty>, } - } else if !writer.sys && !flags.contains(metadata::TypeAttributes::WindowsRuntime) && !metadata::field_is_blittable(f, def) { + } else if !writer.sys + && !flags.contains(metadata::TypeAttributes::WindowsRuntime) + && !metadata::field_is_blittable(f, def) + { if let metadata::Type::Win32Array(ty, len) = ty { let ty = writer.type_default_name(&ty); quote! { pub #name: [core::mem::ManuallyDrop<#ty>; #len], } @@ -94,13 +105,23 @@ fn gen_struct_with_name(writer: &Writer, def: metadata::TypeDef, struct_name: &s for (index, nested_type) in writer.reader.nested_types(def).enumerate() { let nested_name = format!("{struct_name}_{index}"); - tokens.combine(&gen_struct_with_name(writer, nested_type, &nested_name, &cfg)); + tokens.combine(&gen_struct_with_name( + writer, + nested_type, + &nested_name, + &cfg, + )); } tokens } -fn gen_windows_traits(writer: &Writer, def: metadata::TypeDef, name: &TokenStream, cfg: &cfg::Cfg) -> TokenStream { +fn gen_windows_traits( + writer: &Writer, + def: metadata::TypeDef, + name: &TokenStream, + cfg: &cfg::Cfg, +) -> TokenStream { if writer.sys { quote! {} } else { @@ -120,7 +141,10 @@ fn gen_windows_traits(writer: &Writer, def: metadata::TypeDef, name: &TokenStrea } }; - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { let signature = Literal::byte_string(metadata::type_def_signature(def, &[]).as_bytes()); tokens.combine("e! { @@ -138,18 +162,28 @@ fn gen_windows_traits(writer: &Writer, def: metadata::TypeDef, name: &TokenStrea fn gen_derive(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let mut derive = std::collections::BTreeSet::new(); - if !writer.sys && !metadata::type_def_has_explicit_layout(def) && !metadata::type_def_has_packing(def) { + if !writer.sys + && !metadata::type_def_has_explicit_layout(def) + && !metadata::type_def_has_packing(def) + { derive.insert(to_ident("Debug")); } if writer.sys || metadata::type_def_is_copyable(def) { derive.insert(to_ident("Copy")); derive.insert(to_ident("Clone")); - } else if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + } else if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { derive.insert(to_ident("Clone")); } - if !writer.sys && !metadata::type_def_has_explicit_layout(def) && !metadata::type_def_has_packing(def) && !metadata::type_def_has_callback(def) { + if !writer.sys + && !metadata::type_def_has_explicit_layout(def) + && !metadata::type_def_has_packing(def) + && !metadata::type_def_has_callback(def) + { derive.insert(to_ident("PartialEq")); if !metadata::type_def_has_float(def) { @@ -166,8 +200,19 @@ fn gen_derive(writer: &Writer, def: metadata::TypeDef) -> TokenStream { } } -fn gen_clone(writer: &Writer, def: metadata::TypeDef, name: &TokenStream, cfg: &cfg::Cfg) -> TokenStream { - if writer.sys || metadata::type_def_is_copyable(def) || def.flags().contains(metadata::TypeAttributes::WindowsRuntime) || def.class_layout().is_some() { +fn gen_clone( + writer: &Writer, + def: metadata::TypeDef, + name: &TokenStream, + cfg: &cfg::Cfg, +) -> TokenStream { + if writer.sys + || metadata::type_def_is_copyable(def) + || def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + || def.class_layout().is_some() + { quote! {} } else { let features = writer.cfg_features(cfg); @@ -183,7 +228,12 @@ fn gen_clone(writer: &Writer, def: metadata::TypeDef, name: &TokenStream, cfg: & } } -fn gen_struct_constants(writer: &Writer, def: metadata::TypeDef, struct_name: &TokenStream, cfg: &cfg::Cfg) -> TokenStream { +fn gen_struct_constants( + writer: &Writer, + def: metadata::TypeDef, + struct_name: &TokenStream, + cfg: &cfg::Cfg, +) -> TokenStream { let features = writer.cfg_features(cfg); let constants = def.fields().filter_map(|f| { diff --git a/crates/libs/bindgen/src/rust/try_format.rs b/crates/libs/bindgen/src/rust/try_format.rs index 715f9a20ff..d5aeeef423 100644 --- a/crates/libs/bindgen/src/rust/try_format.rs +++ b/crates/libs/bindgen/src/rust/try_format.rs @@ -16,10 +16,24 @@ pub fn try_format(writer: &super::Writer, tokens: &str) -> String { }; // Packaging - e.g. windows/windows-sys crates - assumes the crate will allow whatever warnings it deems fit. - let allow = if writer.package || writer.no_inner_attributes { "" } else { "#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]\n" }; + let allow = if writer.package || writer.no_inner_attributes { + "" + } else { + "#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]\n" + }; let tokens = format!("{preamble}{allow}{tokens}"); - 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 { + let mut cmd = std::process::Command::new("rustfmt"); + cmd.stdin(std::process::Stdio::piped()); + cmd.stdout(std::process::Stdio::piped()); + cmd.stderr(std::process::Stdio::null()); + + if !writer.rustfmt_config.is_empty() { + cmd.arg("--config"); + cmd.arg(writer.rustfmt_config.as_str()); + } + + let Ok(mut child) = cmd.spawn() else { return tokens; }; diff --git a/crates/libs/bindgen/src/rust/winrt_methods.rs b/crates/libs/bindgen/src/rust/winrt_methods.rs index d2b427c6c7..0ac752d43b 100644 --- a/crates/libs/bindgen/src/rust/winrt_methods.rs +++ b/crates/libs/bindgen/src/rust/winrt_methods.rs @@ -1,7 +1,15 @@ use super::*; // TODO take Signature instead of MethodDef (wherever MethodDef is found) -pub fn writer(writer: &Writer, def: metadata::TypeDef, generic_types: &[metadata::Type], kind: metadata::InterfaceKind, method: metadata::MethodDef, method_names: &mut MethodNames, virtual_names: &mut MethodNames) -> TokenStream { +pub fn writer( + writer: &Writer, + def: metadata::TypeDef, + generic_types: &[metadata::Type], + kind: metadata::InterfaceKind, + method: metadata::MethodDef, + method_names: &mut MethodNames, + virtual_names: &mut MethodNames, +) -> TokenStream { let signature = metadata::method_def_signature(def.namespace(), method, generic_types); let params = &signature.params; let name = method_names.add(method); @@ -77,7 +85,9 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, generic_types: &[metadata } } }, - metadata::InterfaceKind::None | metadata::InterfaceKind::Base | metadata::InterfaceKind::Overridable => { + metadata::InterfaceKind::None + | metadata::InterfaceKind::Base + | metadata::InterfaceKind::Overridable => { quote! { #features pub fn #name<#generics>(&self, #params) -> windows_core::Result<#return_type_tokens> #where_clause { @@ -173,8 +183,16 @@ fn gen_winrt_abi_args(writer: &Writer, params: &[metadata::SignatureParam]) -> T tokens } -pub fn gen_upcall(writer: &Writer, sig: &metadata::Signature, inner: TokenStream, this: bool) -> TokenStream { - let invoke_args = sig.params.iter().map(|param| gen_winrt_invoke_arg(writer, param)); +pub fn gen_upcall( + writer: &Writer, + sig: &metadata::Signature, + inner: TokenStream, + this: bool, +) -> TokenStream { + let invoke_args = sig + .params + .iter() + .map(|param| gen_winrt_invoke_arg(writer, param)); let this = if this { quote! { this, } } else { diff --git a/crates/libs/bindgen/src/rust/writer.rs b/crates/libs/bindgen/src/rust/writer.rs index 70cc2e31f0..e6e6189eee 100644 --- a/crates/libs/bindgen/src/rust/writer.rs +++ b/crates/libs/bindgen/src/rust/writer.rs @@ -17,11 +17,13 @@ pub struct Writer { pub sys: bool, // writer sys-style bindings pub flatten: bool, // strips out namespaces - implies !package pub package: bool, // default is single file with no cfg - implies !flatten - pub minimal: bool, // strips out enumerators - in future possibly other helpers as well + 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 no_bindgen_comment: bool, // skips the bindgen comment at the start of the file - pub vtbl: bool, // include minimal vtbl layout support for interfaces + pub no_bindgen_comment: bool, // skips the bindgen comment at the start of the file + pub vtbl: bool, // include minimal vtbl layout support for interfaces pub prepend: std::collections::HashMap, + /// If this is not empty, then it is passed to rustfmt in a `--config` argument. + pub rustfmt_config: String, } impl Writer { @@ -40,6 +42,7 @@ impl Writer { no_bindgen_comment: false, vtbl: false, prepend: Default::default(), + rustfmt_config: String::new(), } } @@ -47,13 +50,26 @@ impl Writer { // metadata::TypeDef // - pub fn type_def_name(&self, def: metadata::TypeDef, generics: &[metadata::Type]) -> TokenStream { + pub fn type_def_name( + &self, + def: metadata::TypeDef, + generics: &[metadata::Type], + ) -> TokenStream { self.type_def_name_imp(def, generics, "") } - pub fn type_def_vtbl_name(&self, def: metadata::TypeDef, generics: &[metadata::Type]) -> TokenStream { + pub fn type_def_vtbl_name( + &self, + def: metadata::TypeDef, + generics: &[metadata::Type], + ) -> TokenStream { self.type_def_name_imp(def, generics, "_Vtbl") } - pub fn type_def_name_imp(&self, def: metadata::TypeDef, generics: &[metadata::Type], suffix: &str) -> TokenStream { + pub fn type_def_name_imp( + &self, + def: metadata::TypeDef, + generics: &[metadata::Type], + suffix: &str, + ) -> TokenStream { let type_name = def.type_name(); if type_name.namespace().is_empty() { @@ -203,7 +219,13 @@ impl Writer { if self.sys { match def.kind() { metadata::TypeKind::Interface => quote! { *mut core::ffi::c_void }, - metadata::TypeKind::Delegate if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) => quote! { *mut core::ffi::c_void }, + metadata::TypeKind::Delegate + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) => + { + quote! { *mut core::ffi::c_void } + } _ => self.type_def_name(*def, generics), } } else { @@ -277,7 +299,10 @@ impl Writer { } } metadata::TypeKind::Delegate => { - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { quote! { *mut core::ffi::c_void } } else { self.type_def_name(*def, &[]) @@ -287,12 +312,20 @@ impl Writer { }, metadata::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) }; + let kind = if *pointers > 1 { + self.type_name(kind) + } else { + self.type_abi_name(kind) + }; quote! { #pointers_tokens #kind } } metadata::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) }; + let kind = if *pointers > 1 { + self.type_name(kind) + } else { + self.type_abi_name(kind) + }; quote! { #pointers_tokens #kind } } metadata::Type::WinrtArray(kind) => self.type_abi_name(kind), @@ -340,12 +373,21 @@ impl Writer { tokens } /// The signature params which are generic (along with their relative index) - pub fn generic_params<'b>(&'b self, params: &'b [metadata::SignatureParam]) -> impl Iterator + 'b { - params.iter().filter(move |param| param.is_convertible()).enumerate() + pub fn generic_params<'b>( + &'b self, + params: &'b [metadata::SignatureParam], + ) -> impl Iterator + 'b { + params + .iter() + .filter(move |param| param.is_convertible()) + .enumerate() } /// The generic param names (i.e., `T` in `fn foo()`) pub fn constraint_generics(&self, params: &[metadata::SignatureParam]) -> TokenStream { - let mut generics = self.generic_params(params).map(|(position, _)| -> TokenStream { format!("P{position}").into() }).peekable(); + let mut generics = self + .generic_params(params) + .map(|(position, _)| -> TokenStream { format!("P{position}").into() }) + .peekable(); if generics.peek().is_some() { quote!(#(#generics),*) @@ -416,7 +458,10 @@ impl Writer { let mut compact = Vec::<&'static str>::new(); if self.package { for feature in cfg.types.keys() { - if !feature.is_empty() && !starts_with(namespace, feature) && !is_defaulted_foundation_feature(namespace, feature) { + if !feature.is_empty() + && !starts_with(namespace, feature) + && !is_defaulted_foundation_feature(namespace, feature) + { for pos in 0..compact.len() { if starts_with(feature, unsafe { compact.get_unchecked(pos) }) { compact.remove(pos); @@ -461,7 +506,8 @@ impl Writer { if self.flatten || namespace == self.namespace { quote! {} } else { - let is_external = namespace.starts_with("Windows.") && !self.namespace.starts_with("Windows"); + 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(); @@ -572,7 +618,13 @@ impl Writer { } } - pub fn agile(&self, def: metadata::TypeDef, ident: &TokenStream, constraints: &TokenStream, features: &TokenStream) -> TokenStream { + pub fn agile( + &self, + def: metadata::TypeDef, + ident: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + ) -> TokenStream { if type_def_is_agile(def) { quote! { #features @@ -584,7 +636,15 @@ impl Writer { quote! {} } } - pub fn async_get(&self, def: metadata::TypeDef, generics: &[metadata::Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, features: &TokenStream) -> TokenStream { + pub fn async_get( + &self, + def: metadata::TypeDef, + generics: &[metadata::Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + features: &TokenStream, + ) -> TokenStream { let mut kind = type_def_async_kind(def); let mut async_generics = generics.to_vec(); @@ -604,13 +664,17 @@ impl Writer { quote! {} } else { let return_type = match kind { - metadata::AsyncKind::Operation | metadata::AsyncKind::OperationWithProgress => self.type_name(&async_generics[0]), + metadata::AsyncKind::Operation | metadata::AsyncKind::OperationWithProgress => { + self.type_name(&async_generics[0]) + } _ => quote! { () }, }; let handler = match kind { metadata::AsyncKind::Action => quote! { AsyncActionCompletedHandler }, - metadata::AsyncKind::ActionWithProgress => quote! { AsyncActionWithProgressCompletedHandler }, + metadata::AsyncKind::ActionWithProgress => { + quote! { AsyncActionWithProgressCompletedHandler } + } metadata::AsyncKind::Operation => quote! { AsyncOperationCompletedHandler }, metadata::AsyncKind::OperationWithProgress => { quote! { AsyncOperationWithProgressCompletedHandler } @@ -657,10 +721,22 @@ impl Writer { } } } - pub fn interface_winrt_trait(&self, def: metadata::TypeDef, generics: &[metadata::Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, features: &TokenStream) -> TokenStream { - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + pub fn interface_winrt_trait( + &self, + def: metadata::TypeDef, + generics: &[metadata::Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { let type_signature = if def.kind() == metadata::TypeKind::Class { - let default = metadata::type_def_default_interface(def).expect("missing default interface"); + let default = + metadata::type_def_default_interface(def).expect("missing default interface"); let default_name = self.type_name(&default); quote! { windows_core::imp::ConstBuffer::for_class::() } } else if generics.is_empty() { @@ -668,7 +744,12 @@ impl Writer { } else { let signature = Literal::byte_string( // TODO: workaround for riddle winmd generation (no attribute support) - if let Some(guid) = metadata::type_def_guid(def) { format!("{{{:#?}}}", guid) } else { "TODO".to_string() }.as_bytes(), + if let Some(guid) = metadata::type_def_guid(def) { + format!("{{{:#?}}}", guid) + } else { + "TODO".to_string() + } + .as_bytes(), ); let generics = generics.iter().enumerate().map(|(index, g)| { @@ -709,8 +790,18 @@ impl Writer { quote! {} } } - pub fn runtime_name_trait(&self, def: metadata::TypeDef, _generics: &[metadata::Type], name: &TokenStream, constraints: &TokenStream, features: &TokenStream) -> TokenStream { - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + pub fn runtime_name_trait( + &self, + def: metadata::TypeDef, + _generics: &[metadata::Type], + name: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { // TODO: this needs to use a ConstBuffer-like facility to accomodate generics let runtime_name = format!("{}", def.type_name()); @@ -728,7 +819,15 @@ impl Writer { } } - pub fn interface_trait(&self, def: metadata::TypeDef, generics: &[metadata::Type], ident: &TokenStream, constraints: &TokenStream, features: &TokenStream, has_unknown_base: bool) -> TokenStream { + pub fn interface_trait( + &self, + def: metadata::TypeDef, + generics: &[metadata::Type], + ident: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + has_unknown_base: bool, + ) -> TokenStream { if let Some(default) = metadata::type_def_default_interface(def) { let default_name = self.type_name(&default); let vtbl = self.type_vtbl_name(&default); @@ -773,7 +872,13 @@ impl Writer { } } } - pub fn interface_vtbl(&self, def: metadata::TypeDef, generics: &[metadata::Type], constraints: &TokenStream, features: &TokenStream) -> TokenStream { + pub fn interface_vtbl( + &self, + def: metadata::TypeDef, + generics: &[metadata::Type], + constraints: &TokenStream, + features: &TokenStream, + ) -> TokenStream { let vtbl = self.type_def_vtbl_name(def, generics); let mut methods = quote! {}; let mut method_names = MethodNames::new(); @@ -781,8 +886,12 @@ impl Writer { let crate_name = self.crate_name(); match metadata::type_def_vtables(def).last() { - Some(metadata::Type::Name(metadata::TypeName::IUnknown)) => methods.combine("e! { pub base__: #crate_name IUnknown_Vtbl, }), - Some(metadata::Type::Object) => methods.combine("e! { pub base__: #crate_name IInspectable_Vtbl, }), + Some(metadata::Type::Name(metadata::TypeName::IUnknown)) => { + methods.combine("e! { pub base__: #crate_name IUnknown_Vtbl, }) + } + Some(metadata::Type::Object) => { + methods.combine("e! { pub base__: #crate_name IInspectable_Vtbl, }) + } Some(metadata::Type::TypeDef(def, _)) => { let vtbl = self.type_def_vtbl_name(*def, &[]); methods.combine("e! { pub base__: #vtbl, }); @@ -831,28 +940,53 @@ impl Writer { } } } - pub fn vtbl_signature(&self, def: metadata::TypeDef, named_params: bool, signature: &metadata::Signature) -> TokenStream { - let is_winrt = def.flags().contains(metadata::TypeAttributes::WindowsRuntime); + pub fn vtbl_signature( + &self, + def: metadata::TypeDef, + named_params: bool, + signature: &metadata::Signature, + ) -> TokenStream { + let is_winrt = def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime); let crate_name = self.crate_name(); let (trailing_return_type, return_type, udt_return_type) = match &signature.return_type { - metadata::Type::Void if is_winrt => (quote! {}, quote! { -> #crate_name HRESULT }, quote! {}), + metadata::Type::Void if is_winrt => { + (quote! {}, quote! { -> #crate_name HRESULT }, quote! {}) + } metadata::Type::Void => (quote! {}, quote! {}, quote! {}), metadata::Type::WinrtArray(kind) => { let tokens = self.type_abi_name(kind); if named_params { - (quote! { result_size__: *mut u32, result__: *mut *mut #tokens }, quote! { -> #crate_name HRESULT }, quote! {}) + ( + quote! { result_size__: *mut u32, result__: *mut *mut #tokens }, + quote! { -> #crate_name HRESULT }, + quote! {}, + ) } else { - (quote! { *mut u32, *mut *mut #tokens }, quote! { -> #crate_name HRESULT }, quote! {}) + ( + quote! { *mut u32, *mut *mut #tokens }, + quote! { -> #crate_name HRESULT }, + quote! {}, + ) } } _ if is_winrt => { let tokens = self.type_abi_name(&signature.return_type); if named_params { - (quote! { result__: *mut #tokens }, quote! { -> #crate_name HRESULT }, quote! {}) + ( + quote! { result__: *mut #tokens }, + quote! { -> #crate_name HRESULT }, + quote! {}, + ) } else { - (quote! { *mut #tokens }, quote! { -> #crate_name HRESULT }, quote! {}) + ( + quote! { *mut #tokens }, + quote! { -> #crate_name HRESULT }, + quote! {}, + ) } } _ if metadata::type_is_struct(&signature.return_type) => { @@ -945,7 +1079,9 @@ impl Writer { } pub fn return_sig(&self, signature: &metadata::Signature) -> TokenStream { match &signature.return_type { - metadata::Type::Void if signature.def.has_attribute("DoesNotReturnAttribute") => " -> !".into(), + metadata::Type::Void if signature.def.has_attribute("DoesNotReturnAttribute") => { + " -> !".into() + } metadata::Type::Void => TokenStream::new(), _ => { let tokens = self.type_default_name(&signature.return_type); @@ -953,7 +1089,11 @@ impl Writer { } } } - pub fn win32_args(&self, params: &[metadata::SignatureParam], kind: metadata::SignatureKind) -> TokenStream { + pub fn win32_args( + &self, + params: &[metadata::SignatureParam], + kind: metadata::SignatureKind, + ) -> TokenStream { let mut tokens = quote! {}; for (position, param) in params.iter().enumerate() { @@ -961,20 +1101,27 @@ impl Writer { metadata::SignatureKind::Query(query) if query.object == position => { quote! { &mut result__, } } - metadata::SignatureKind::ReturnValue | metadata::SignatureKind::ResultValue if params.len() - 1 == position => { + metadata::SignatureKind::ReturnValue | metadata::SignatureKind::ResultValue + if params.len() - 1 == position => + { quote! { &mut result__, } } metadata::SignatureKind::QueryOptional(query) if query.object == position => { quote! { result__ as *mut _ as *mut _, } } - metadata::SignatureKind::Query(query) | metadata::SignatureKind::QueryOptional(query) if query.guid == position => { + metadata::SignatureKind::Query(query) + | metadata::SignatureKind::QueryOptional(query) + if query.guid == position => + { quote! { &T::IID, } } _ => { let name = self.param_name(param.def); let flags = param.def.flags(); match param.kind { - metadata::SignatureParamKind::ArrayFixed(_) | metadata::SignatureParamKind::ArrayRelativeLen(_) | metadata::SignatureParamKind::ArrayRelativeByteLen(_) => { + metadata::SignatureParamKind::ArrayFixed(_) + | metadata::SignatureParamKind::ArrayRelativeLen(_) + | metadata::SignatureParamKind::ArrayRelativeByteLen(_) => { let map = if flags.contains(metadata::ParamAttributes::Optional) { quote! { #name.as_deref().map_or(core::ptr::null(), |slice|slice.as_ptr()) } } else { @@ -1022,18 +1169,25 @@ impl Writer { tokens } - pub fn win32_params(&self, params: &[metadata::SignatureParam], kind: metadata::SignatureKind) -> TokenStream { + pub fn win32_params( + &self, + params: &[metadata::SignatureParam], + kind: metadata::SignatureKind, + ) -> TokenStream { let mut tokens = quote! {}; let mut generic_params = self.generic_params(params); for (position, param) in params.iter().enumerate() { match kind { - metadata::SignatureKind::Query(query) | metadata::SignatureKind::QueryOptional(query) => { + metadata::SignatureKind::Query(query) + | metadata::SignatureKind::QueryOptional(query) => { if query.object == position || query.guid == position { continue; } } - metadata::SignatureKind::ReturnValue | metadata::SignatureKind::ResultValue if params.len() - 1 == position => { + metadata::SignatureKind::ReturnValue | metadata::SignatureKind::ResultValue + if params.len() - 1 == position => + { continue; } _ => {} @@ -1051,7 +1205,11 @@ impl Writer { } else { quote! { &[#ty; #len] } }; - if param.def.flags().contains(metadata::ParamAttributes::Optional) { + if param + .def + .flags() + .contains(metadata::ParamAttributes::Optional) + { tokens.combine("e! { #name: Option<#ty>, }); } else { tokens.combine("e! { #name: #ty, }); @@ -1065,7 +1223,11 @@ impl Writer { } else { quote! { &[#ty] } }; - if param.def.flags().contains(metadata::ParamAttributes::Optional) { + if param + .def + .flags() + .contains(metadata::ParamAttributes::Optional) + { tokens.combine("e! { #name: Option<#ty>, }); } else { tokens.combine("e! { #name: #ty, }); @@ -1077,7 +1239,11 @@ impl Writer { } else { quote! { &[u8] } }; - if param.def.flags().contains(metadata::ParamAttributes::Optional) { + if param + .def + .flags() + .contains(metadata::ParamAttributes::Optional) + { tokens.combine("e! { #name: Option<#ty>, }); } else { tokens.combine("e! { #name: #ty, }); @@ -1093,7 +1259,8 @@ impl Writer { let kind = self.type_default_name(¶m.ty); tokens.combine("e! { #name: Option<#kind>, }); } - metadata::SignatureParamKind::ValueType | metadata::SignatureParamKind::Blittable => { + metadata::SignatureParamKind::ValueType + | metadata::SignatureParamKind::Blittable => { let kind = self.type_default_name(¶m.ty); tokens.combine("e! { #name: #kind, }); } @@ -1107,10 +1274,20 @@ impl Writer { tokens } - pub fn impl_signature(&self, def: metadata::TypeDef, signature: &metadata::Signature) -> TokenStream { - if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { + pub fn impl_signature( + &self, + def: metadata::TypeDef, + signature: &metadata::Signature, + ) -> TokenStream { + if def + .flags() + .contains(metadata::TypeAttributes::WindowsRuntime) + { let is_delegate = def.kind() == metadata::TypeKind::Delegate; - let params = signature.params.iter().map(|p| self.winrt_produce_type(p, !is_delegate)); + let params = signature + .params + .iter() + .map(|p| self.winrt_produce_type(p, !is_delegate)); let return_type = match &signature.return_type { metadata::Type::Void => quote! { () }, @@ -1148,7 +1325,9 @@ impl Writer { let return_type = match signature_kind { metadata::SignatureKind::ReturnVoid => quote! {}, - metadata::SignatureKind::Query(_) | metadata::SignatureKind::QueryOptional(_) | metadata::SignatureKind::ResultVoid => quote! { -> windows_core::Result<()> }, + metadata::SignatureKind::Query(_) + | metadata::SignatureKind::QueryOptional(_) + | metadata::SignatureKind::ResultVoid => quote! { -> windows_core::Result<()> }, metadata::SignatureKind::ResultValue => { let return_type = signature.params[signature.params.len() - 1].ty.deref(); let return_type = self.type_name(&return_type); @@ -1161,7 +1340,11 @@ impl Writer { quote! { (&self, #params) #return_type } } } - fn winrt_produce_type(&self, param: &metadata::SignatureParam, include_param_names: bool) -> TokenStream { + fn winrt_produce_type( + &self, + param: &metadata::SignatureParam, + include_param_names: bool, + ) -> TokenStream { let default_type = self.type_default_name(¶m.ty); let sig = if param.def.flags().contains(metadata::ParamAttributes::In) { @@ -1270,7 +1453,8 @@ fn starts_with(namespace: &str, feature: &str) -> bool { } fn is_defaulted_foundation_feature(namespace: &str, feature: &str) -> bool { - let is_winrt = !starts_with(namespace, "Windows.Win32") && !starts_with(namespace, "Windows.Wdk"); + let is_winrt = + !starts_with(namespace, "Windows.Win32") && !starts_with(namespace, "Windows.Wdk"); if !is_winrt && feature == "Windows.Win32.Foundation" { true @@ -1292,7 +1476,9 @@ fn type_def_async_kind(row: metadata::TypeDef) -> metadata::AsyncKind { metadata::TypeName::IAsyncAction => metadata::AsyncKind::Action, metadata::TypeName::IAsyncActionWithProgress => metadata::AsyncKind::ActionWithProgress, metadata::TypeName::IAsyncOperation => metadata::AsyncKind::Operation, - metadata::TypeName::IAsyncOperationWithProgress => metadata::AsyncKind::OperationWithProgress, + metadata::TypeName::IAsyncOperationWithProgress => { + metadata::AsyncKind::OperationWithProgress + } _ => metadata::AsyncKind::None, } } @@ -1311,7 +1497,13 @@ fn type_def_is_agile(row: metadata::TypeDef) -> bool { _ => {} } } - matches!(row.type_name(), metadata::TypeName::IAsyncAction | metadata::TypeName::IAsyncActionWithProgress | metadata::TypeName::IAsyncOperation | metadata::TypeName::IAsyncOperationWithProgress) + matches!( + row.type_name(), + metadata::TypeName::IAsyncAction + | metadata::TypeName::IAsyncActionWithProgress + | metadata::TypeName::IAsyncOperation + | metadata::TypeName::IAsyncOperationWithProgress + ) } #[cfg(test)] @@ -1320,9 +1512,21 @@ mod tests { #[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")); + 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/crates/libs/bindgen/src/tokens/mod.rs b/crates/libs/bindgen/src/tokens/mod.rs index 12a54142fa..dc37ea3e35 100644 --- a/crates/libs/bindgen/src/tokens/mod.rs +++ b/crates/libs/bindgen/src/tokens/mod.rs @@ -435,7 +435,12 @@ macro_rules! quote_token { 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(), + "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(), _ => name.into(), diff --git a/crates/libs/bindgen/src/tokens/token_stream.rs b/crates/libs/bindgen/src/tokens/token_stream.rs index 0218a3bb69..559c24e230 100644 --- a/crates/libs/bindgen/src/tokens/token_stream.rs +++ b/crates/libs/bindgen/src/tokens/token_stream.rs @@ -136,7 +136,9 @@ pub struct Literal { macro_rules! unsuffixed { ($ty:ty => $name:ident) => { pub fn $name(n: $ty) -> Self { - Self { inner: n.to_string() } + Self { + inner: n.to_string(), + } } }; } @@ -149,7 +151,12 @@ impl Literal { unsuffixed!(u8 => u8_unsuffixed); pub fn byte_string(s: &[u8]) -> Self { - Self { inner: format!("b\"{}\"", core::str::from_utf8(s).expect("Could not turn bytes into byte literal")) } + Self { + inner: format!( + "b\"{}\"", + core::str::from_utf8(s).expect("Could not turn bytes into byte literal") + ), + } } pub fn as_str(&self) -> &str { diff --git a/crates/libs/bindgen/src/tree.rs b/crates/libs/bindgen/src/tree.rs index 6a619940eb..ebbf84134a 100644 --- a/crates/libs/bindgen/src/tree.rs +++ b/crates/libs/bindgen/src/tree.rs @@ -18,18 +18,30 @@ impl Tree { } fn from_namespace(namespace: &'static str) -> Self { - Self { namespace, nested: std::collections::BTreeMap::new() } + Self { + namespace, + nested: std::collections::BTreeMap::new(), + } } fn insert_namespace(&mut self, namespace: &'static str, pos: usize) -> &mut Self { if let Some(next) = namespace[pos..].find('.') { let next = pos + next; - self.nested.entry(&namespace[pos..next]).or_insert_with(|| Self::from_namespace(&namespace[..next])).insert_namespace(namespace, next + 1) + self.nested + .entry(&namespace[pos..next]) + .or_insert_with(|| Self::from_namespace(&namespace[..next])) + .insert_namespace(namespace, next + 1) } else { - self.nested.entry(&namespace[pos..]).or_insert_with(|| Self::from_namespace(namespace)) + self.nested + .entry(&namespace[pos..]) + .or_insert_with(|| Self::from_namespace(namespace)) } } pub fn flatten(&self) -> Vec<&Self> { - let mut flatten = if self.namespace.is_empty() { vec![] } else { vec![self] }; + let mut flatten = if self.namespace.is_empty() { + vec![] + } else { + vec![self] + }; flatten.extend(self.nested.values().flat_map(|tree| tree.flatten())); flatten } diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs index c596ce85d2..b01d92f066 100644 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ b/crates/libs/bindgen/src/winmd/from_reader.rs @@ -1,7 +1,11 @@ use super::*; use metadata::{AsRow, HasAttributes}; -pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { +pub fn from_reader( + reader: &metadata::Reader, + config: std::collections::BTreeMap<&str, &str>, + output: &str, +) -> Result<()> { let mut writer = Writer::new(output); // TODO: do we need any configuration values for winmd generation? @@ -23,7 +27,11 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let generics = &metadata::type_def_generics(def); - let extends = if let Some(extends) = def.extends() { writer.insert_type_ref(extends.namespace(), extends.name()) } else { TypeDefOrRef::none() }; + let extends = if let Some(extends) = def.extends() { + writer.insert_type_ref(extends.namespace(), extends.name()) + } else { + TypeDefOrRef::none() + }; writer.tables.TypeDef.push(TypeDef { Extends: extends, @@ -49,14 +57,21 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let ty = winmd_type(&interface.ty); let reference = match &ty { - Type::TypeRef(type_name) if type_name.generics.is_empty() => writer.insert_type_ref(&type_name.namespace, &type_name.name), + Type::TypeRef(type_name) if type_name.generics.is_empty() => { + writer.insert_type_ref(&type_name.namespace, &type_name.name) + } Type::TypeRef(_) => writer.insert_type_spec(ty), Type::IUnknown => writer.insert_type_ref("Windows.Win32.System.Com", "IUnknown"), - Type::IInspectable => writer.insert_type_ref("Windows.Win32.System.WinRT", "IInspectable"), + Type::IInspectable => { + writer.insert_type_ref("Windows.Win32.System.WinRT", "IInspectable") + } rest => unimplemented!("{rest:?}"), }; - writer.tables.InterfaceImpl.push(InterfaceImpl { Class: def_ref, Interface: reference }); + writer.tables.InterfaceImpl.push(InterfaceImpl { + Class: def_ref, + Interface: reference, + }); } // TODO: if the class is "Apis" then should we sort the fields (constants) and methods (functions) for stability @@ -65,10 +80,18 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let ty = winmd_type(&field.ty(Some(def))); let signature = writer.insert_field_sig(&ty); - writer.tables.Field.push(Field { Flags: field.flags().0, Name: writer.strings.insert(field.name()), Signature: signature }); + writer.tables.Field.push(Field { + Flags: field.flags().0, + Name: writer.strings.insert(field.name()), + Signature: signature, + }); if let Some(constant) = field.constant() { - writer.tables.Constant.push(Constant { Type: constant.usize(0) as u16, Parent: HasConstant::Field(writer.tables.Field.len() as u32 - 1), Value: writer.blobs.insert(&constant.blob(2)) }) + writer.tables.Constant.push(Constant { + Type: constant.usize(0) as u16, + Parent: HasConstant::Field(writer.tables.Field.len() as u32 - 1), + Value: writer.blobs.insert(&constant.blob(2)), + }) } } @@ -77,7 +100,8 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let return_type = winmd_type(&signature.return_type); let param_types: Vec = signature.params.iter().map(winmd_type).collect(); - let signature = writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); + let signature = + writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); writer.tables.MethodDef.push(MethodDef { RVA: 0, @@ -89,7 +113,11 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap }); for param in method.params() { - writer.tables.Param.push(Param { Flags: param.flags().0, Sequence: param.sequence(), Name: writer.strings.insert(param.name()) }); + writer.tables.Param.push(Param { + Flags: param.flags().0, + Sequence: param.sequence(), + Name: writer.strings.insert(param.name()), + }); } } @@ -98,14 +126,25 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap assert_eq!(attribute_ctor.name(), ".ctor"); let metadata::MemberRefParent::TypeRef(attribute_type) = attribute_ctor.parent(); - let attribute_type_ref = if let TypeDefOrRef::TypeRef(type_ref) = writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()) { MemberRefParent::TypeRef(type_ref) } else { panic!() }; + let attribute_type_ref = if let TypeDefOrRef::TypeRef(type_ref) = + writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()) + { + MemberRefParent::TypeRef(type_ref) + } else { + panic!() + }; let signature = attribute_ctor.signature(); let return_type = winmd_type(&signature.return_type); let param_types: Vec = signature.params.iter().map(winmd_type).collect(); - let signature = writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); + let signature = + writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); - writer.tables.MemberRef.push(MemberRef { Class: attribute_type_ref, Name: writer.strings.insert(".ctor"), Signature: signature }); + writer.tables.MemberRef.push(MemberRef { + Class: attribute_type_ref, + Name: writer.strings.insert(".ctor"), + Signature: signature, + }); let mut values = 1u16.to_le_bytes().to_vec(); // prolog let args = attribute.args(); @@ -128,7 +167,11 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let values = writer.blobs.insert(&values); - writer.tables.CustomAttribute.push(CustomAttribute { Parent: HasAttribute::TypeDef(def_ref), Type: AttributeType::MemberRef(writer.tables.MemberRef.len() as u32 - 1), Value: values }); + writer.tables.CustomAttribute.push(CustomAttribute { + Parent: HasAttribute::TypeDef(def_ref), + Type: AttributeType::MemberRef(writer.tables.MemberRef.len() as u32 - 1), + Value: values, + }); } } @@ -195,13 +238,19 @@ fn winmd_type(ty: &metadata::Type) -> Type { metadata::Type::Const(metadata::TypeName::PWSTR) => Type::PCWSTR, metadata::Type::Name(metadata::TypeName::BSTR) => Type::BSTR, metadata::Type::Name(metadata::TypeName::Type) => Type::Type, - metadata::Type::TypeDef(def, generics) => Type::TypeRef(TypeName { namespace: def.namespace().to_string(), name: def.name().to_string(), generics: generics.iter().map(winmd_type).collect() }), + metadata::Type::TypeDef(def, generics) => Type::TypeRef(TypeName { + namespace: def.namespace().to_string(), + name: def.name().to_string(), + generics: generics.iter().map(winmd_type).collect(), + }), metadata::Type::GenericParam(generic) => Type::GenericParam(generic.number()), metadata::Type::ConstRef(ty) => Type::ConstRef(Box::new(winmd_type(ty))), metadata::Type::WinrtArrayRef(ty) => Type::WinrtArrayRef(Box::new(winmd_type(ty))), metadata::Type::WinrtArray(ty) => Type::WinrtArray(Box::new(winmd_type(ty))), metadata::Type::MutPtr(ty, pointers) => Type::MutPtr(Box::new(winmd_type(ty)), *pointers), - metadata::Type::ConstPtr(ty, pointers) => Type::ConstPtr(Box::new(winmd_type(ty)), *pointers), + metadata::Type::ConstPtr(ty, pointers) => { + Type::ConstPtr(Box::new(winmd_type(ty)), *pointers) + } metadata::Type::Win32Array(ty, len) => Type::Win32Array(Box::new(winmd_type(ty)), *len), rest => unimplemented!("{rest:?}"), } diff --git a/crates/libs/bindgen/src/winmd/writer/blobs.rs b/crates/libs/bindgen/src/winmd/writer/blobs.rs index f24bac338a..2393399fb1 100644 --- a/crates/libs/bindgen/src/winmd/writer/blobs.rs +++ b/crates/libs/bindgen/src/winmd/writer/blobs.rs @@ -7,7 +7,10 @@ pub struct Blobs { impl Default for Blobs { fn default() -> Self { - Self { map: Default::default(), stream: vec![0] } + Self { + map: Default::default(), + stream: vec![0], + } } } diff --git a/crates/libs/bindgen/src/winmd/writer/file.rs b/crates/libs/bindgen/src/winmd/writer/file.rs index 9d69fe94d1..8f480d6294 100644 --- a/crates/libs/bindgen/src/winmd/writer/file.rs +++ b/crates/libs/bindgen/src/winmd/writer/file.rs @@ -1,7 +1,10 @@ use super::*; pub fn write(mut tables: Vec, mut strings: Vec, mut blobs: Vec) -> Vec { - if [tables.len(), strings.len(), blobs.len()].iter().any(|len| *len > u32::MAX as usize) { + if [tables.len(), strings.len(), blobs.len()] + .iter() + .any(|len| *len > u32::MAX as usize) + { panic!("heap too large"); } @@ -17,8 +20,11 @@ pub fn write(mut tables: Vec, mut strings: Vec, mut blobs: Vec) -> V let mut file: metadata::IMAGE_FILE_HEADER = core::mem::zeroed(); file.Machine = metadata::IMAGE_FILE_MACHINE_I386; file.NumberOfSections = 1; - file.SizeOfOptionalHeader = core::mem::size_of::() as u16; - file.Characteristics = metadata::IMAGE_FILE_DLL | metadata::IMAGE_FILE_32BIT_MACHINE | metadata::IMAGE_FILE_EXECUTABLE_IMAGE; + file.SizeOfOptionalHeader = + core::mem::size_of::() as u16; + file.Characteristics = metadata::IMAGE_FILE_DLL + | metadata::IMAGE_FILE_32BIT_MACHINE + | metadata::IMAGE_FILE_EXECUTABLE_IMAGE; let mut optional: metadata::IMAGE_OPTIONAL_HEADER32 = core::mem::zeroed(); optional.Magic = metadata::IMAGE_NT_OPTIONAL_HDR32_MAGIC; @@ -33,7 +39,9 @@ pub fn write(mut tables: Vec, mut strings: Vec, mut blobs: Vec) -> V optional.MinorSubsystemVersion = 2; optional.SizeOfHeaders = 512; optional.Subsystem = metadata::IMAGE_SUBSYSTEM_WINDOWS_CUI; - optional.DllCharacteristics = metadata::IMAGE_DLLCHARACTERISTICS_NX_COMPAT | metadata::IMAGE_DLLCHARACTERISTICS_NO_SEH | metadata::IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; + optional.DllCharacteristics = metadata::IMAGE_DLLCHARACTERISTICS_NX_COMPAT + | metadata::IMAGE_DLLCHARACTERISTICS_NO_SEH + | metadata::IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; optional.SizeOfStackReserve = 0x100000; optional.SizeOfHeapReserve = 4096; optional.LoaderFlags = 0x100000; @@ -65,17 +73,32 @@ pub fn write(mut tables: Vec, mut strings: Vec, mut blobs: Vec) -> V type GuidsHeader = StreamHeader<8>; type BlobsHeader = StreamHeader<8>; - let size_of_stream_headers = core::mem::size_of::() + core::mem::size_of::() + core::mem::size_of::() + core::mem::size_of::(); - let size_of_image = optional.FileAlignment as usize + core::mem::size_of::() + core::mem::size_of::() + size_of_stream_headers + size_of_streams; + let size_of_stream_headers = core::mem::size_of::() + + core::mem::size_of::() + + core::mem::size_of::() + + core::mem::size_of::(); + let size_of_image = optional.FileAlignment as usize + + core::mem::size_of::() + + core::mem::size_of::() + + size_of_stream_headers + + size_of_streams; optional.SizeOfImage = round(size_of_image, optional.SectionAlignment as usize) as u32; section.Misc.VirtualSize = size_of_image as u32 - optional.FileAlignment; - section.SizeOfRawData = round(section.Misc.VirtualSize as usize, optional.FileAlignment as usize) as u32; - - optional.DataDirectory[14] = metadata::IMAGE_DATA_DIRECTORY { VirtualAddress: SECTION_ALIGNMENT, Size: core::mem::size_of::() as u32 }; + section.SizeOfRawData = round( + section.Misc.VirtualSize as usize, + optional.FileAlignment as usize, + ) as u32; + + optional.DataDirectory[14] = metadata::IMAGE_DATA_DIRECTORY { + VirtualAddress: SECTION_ALIGNMENT, + Size: core::mem::size_of::() as u32, + }; section.PointerToRawData = optional.FileAlignment; - clr.MetaData.VirtualAddress = SECTION_ALIGNMENT + core::mem::size_of::() as u32; - clr.MetaData.Size = section.Misc.VirtualSize - core::mem::size_of::() as u32; + clr.MetaData.VirtualAddress = + SECTION_ALIGNMENT + core::mem::size_of::() as u32; + clr.MetaData.Size = + section.Misc.VirtualSize - core::mem::size_of::() as u32; let mut buffer = Vec::::new(); @@ -92,9 +115,21 @@ pub fn write(mut tables: Vec, mut strings: Vec, mut blobs: Vec) -> V let stream_offset = buffer.len() - metadata_offset + size_of_stream_headers; let tables_header = TablesHeader::new(stream_offset as u32, tables.len() as u32, b"#~\0\0"); - let strings_header = StringsHeader::new(tables_header.next_offset(), strings.len() as u32, b"#Strings\0\0\0\0"); - let guids_header = GuidsHeader::new(strings_header.next_offset(), guids.len() as u32, b"#GUID\0\0\0"); - let blobs_header = BlobsHeader::new(guids_header.next_offset(), blobs.len() as u32, b"#Blob\0\0\0"); + let strings_header = StringsHeader::new( + tables_header.next_offset(), + strings.len() as u32, + b"#Strings\0\0\0\0", + ); + let guids_header = GuidsHeader::new( + strings_header.next_offset(), + guids.len() as u32, + b"#GUID\0\0\0", + ); + let blobs_header = BlobsHeader::new( + guids_header.next_offset(), + blobs.len() as u32, + b"#Blob\0\0\0", + ); buffer.write_header(&tables_header); buffer.write_header(&strings_header); @@ -124,7 +159,11 @@ struct StreamHeader { impl StreamHeader { fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self { - Self { offset, size, name: *name } + Self { + offset, + size, + name: *name, + } } fn next_offset(&self) -> u32 { self.offset + self.size diff --git a/crates/libs/bindgen/src/winmd/writer/mod.rs b/crates/libs/bindgen/src/winmd/writer/mod.rs index 1ad0086db3..b485d7edf3 100644 --- a/crates/libs/bindgen/src/winmd/writer/mod.rs +++ b/crates/libs/bindgen/src/winmd/writer/mod.rs @@ -36,11 +36,24 @@ impl Writer { type_specs: Default::default(), }; - writer.tables.TypeDef.push(TypeDef { TypeName: writer.strings.insert(""), Flags: 0, TypeNamespace: 0, Extends: TypeDefOrRef::none(), FieldList: 0, MethodList: 0 }); + writer.tables.TypeDef.push(TypeDef { + TypeName: writer.strings.insert(""), + Flags: 0, + TypeNamespace: 0, + Extends: TypeDefOrRef::none(), + FieldList: 0, + MethodList: 0, + }); - let name = name.rsplit_once(&['/', '\\']).map_or(name, |(_, name)| name); + let name = name + .rsplit_once(&['/', '\\']) + .map_or(name, |(_, name)| name); - writer.tables.Module.push(Module { Name: writer.strings.insert(name), Mvid: 1, ..Default::default() }); + writer.tables.Module.push(Module { + Name: writer.strings.insert(name), + Mvid: 1, + ..Default::default() + }); let name = name.rsplit_once('.').map_or(name, |(_, name)| name); @@ -63,10 +76,19 @@ impl Writer { } pub fn into_stream(self) -> Vec { - file::write(self.tables.into_stream(), self.strings.into_stream(), self.blobs.into_stream()) + file::write( + self.tables.into_stream(), + self.strings.into_stream(), + self.blobs.into_stream(), + ) } - pub fn insert_method_sig(&mut self, call_flags: metadata::MethodCallAttributes, return_type: &Type, param_types: &[Type]) -> u32 { + pub fn insert_method_sig( + &mut self, + call_flags: metadata::MethodCallAttributes, + return_type: &Type, + param_types: &[Type], + ) -> u32 { let mut blob = vec![call_flags.0]; usize_blob(param_types.len(), &mut blob); self.type_blob(return_type, &mut blob); @@ -92,12 +114,16 @@ impl Writer { if let Some(scope) = self.scopes.get(namespace) { *scope } else if namespace == "System" { - let scope = ResolutionScope::AssemblyRef(self.tables.AssemblyRef.push2(AssemblyRef { - Name: self.strings.insert("mscorlib"), - MajorVersion: 4, - PublicKeyOrToken: self.blobs.insert(&[0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89]), // TODO: comment on this - ..Default::default() - })); + let scope = ResolutionScope::AssemblyRef( + self.tables.AssemblyRef.push2(AssemblyRef { + Name: self.strings.insert("mscorlib"), + MajorVersion: 4, + PublicKeyOrToken: self + .blobs + .insert(&[0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89]), // TODO: comment on this + ..Default::default() + }), + ); self.scopes.insert(namespace.to_string(), scope); scope } else { @@ -125,8 +151,15 @@ impl Writer { let scope = self.insert_scope(namespace); - let reference = TypeDefOrRef::TypeRef(self.tables.TypeRef.push2(TypeRef { TypeName: self.strings.insert(name), TypeNamespace: self.strings.insert(namespace), ResolutionScope: scope })); - self.type_refs.entry(namespace.to_string()).or_default().insert(name.to_string(), reference); + let reference = TypeDefOrRef::TypeRef(self.tables.TypeRef.push2(TypeRef { + TypeName: self.strings.insert(name), + TypeNamespace: self.strings.insert(namespace), + ResolutionScope: scope, + })); + self.type_refs + .entry(namespace.to_string()) + .or_default() + .insert(name.to_string(), reference); reference } @@ -139,7 +172,9 @@ impl Writer { self.type_blob(&ty, &mut blob); let signature = self.blobs.insert(&blob); - let reference = TypeDefOrRef::TypeSpec(self.tables.TypeSpec.push2(TypeSpec { Signature: signature })); + let reference = TypeDefOrRef::TypeSpec(self.tables.TypeSpec.push2(TypeSpec { + Signature: signature, + })); self.type_specs.insert(ty, reference); reference } @@ -211,7 +246,11 @@ impl Writer { } Type::ConstRef(ty) => { usize_blob(metadata::ELEMENT_TYPE_CMOD_OPT as usize, blob); - usize_blob(self.insert_type_ref("System.Runtime.CompilerServices", "IsConst").encode() as usize, blob); + usize_blob( + self.insert_type_ref("System.Runtime.CompilerServices", "IsConst") + .encode() as usize, + blob, + ); usize_blob(metadata::ELEMENT_TYPE_BYREF as usize, blob); self.type_blob(ty, blob); } diff --git a/crates/libs/bindgen/src/winmd/writer/strings.rs b/crates/libs/bindgen/src/winmd/writer/strings.rs index 1eeae6d43b..f7c3dd9c06 100644 --- a/crates/libs/bindgen/src/winmd/writer/strings.rs +++ b/crates/libs/bindgen/src/winmd/writer/strings.rs @@ -8,7 +8,10 @@ pub struct Strings { impl Default for Strings { fn default() -> Self { - Self { map: Default::default(), stream: vec![0] } + Self { + map: Default::default(), + stream: vec![0], + } } } diff --git a/crates/libs/bindgen/src/winmd/writer/tables.rs b/crates/libs/bindgen/src/winmd/writer/tables.rs index 1c4d60b455..7f055e5853 100644 --- a/crates/libs/bindgen/src/winmd/writer/tables.rs +++ b/crates/libs/bindgen/src/winmd/writer/tables.rs @@ -170,17 +170,79 @@ pub struct TypeSpec { impl Tables { pub fn into_stream(self) -> Vec { - if [self.AssemblyRef.len(), self.ClassLayout.len(), self.Constant.len(), self.CustomAttribute.len(), self.Field.len(), self.GenericParam.len(), self.ImplMap.len(), self.InterfaceImpl.len(), self.MemberRef.len(), self.MethodDef.len(), self.Module.len(), self.ModuleRef.len(), self.NestedClass.len(), self.Param.len(), self.Property.len(), self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()].iter().any(|len| *len > u32::MAX as usize) { + if [ + self.AssemblyRef.len(), + self.ClassLayout.len(), + self.Constant.len(), + self.CustomAttribute.len(), + self.Field.len(), + self.GenericParam.len(), + self.ImplMap.len(), + self.InterfaceImpl.len(), + self.MemberRef.len(), + self.MethodDef.len(), + self.Module.len(), + self.ModuleRef.len(), + self.NestedClass.len(), + self.Param.len(), + self.Property.len(), + self.TypeDef.len(), + self.TypeRef.len(), + self.TypeSpec.len(), + ] + .iter() + .any(|len| *len > u32::MAX as usize) + { panic!("metadata table too large"); } - let resolution_scope = metadata::coded_index_size(&[self.Module.len(), self.ModuleRef.len(), self.AssemblyRef.len(), self.TypeRef.len()]); - let type_def_or_ref = metadata::coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()]); - let has_constant = metadata::coded_index_size(&[self.Field.len(), self.Param.len(), self.Property.len()]); - let type_or_method_def = metadata::coded_index_size(&[self.TypeDef.len(), self.MethodDef.len()]); - let member_ref_parent = metadata::coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.ModuleRef.len(), self.MethodDef.len(), self.TypeSpec.len()]); - let custom_attribute_type = metadata::coded_index_size(&[self.MethodDef.len(), self.MemberRef.len(), 0, 0, 0]); - let has_custom_attribute = metadata::coded_index_size(&[self.MethodDef.len(), self.Field.len(), self.TypeRef.len(), self.TypeDef.len(), self.Param.len(), self.InterfaceImpl.len(), self.MemberRef.len(), self.Module.len(), 0, 0, 0, self.ModuleRef.len(), self.TypeSpec.len(), 0, self.AssemblyRef.len(), 0, 0, 0, self.GenericParam.len(), 0, 0]); + let resolution_scope = metadata::coded_index_size(&[ + self.Module.len(), + self.ModuleRef.len(), + self.AssemblyRef.len(), + self.TypeRef.len(), + ]); + let type_def_or_ref = metadata::coded_index_size(&[ + self.TypeDef.len(), + self.TypeRef.len(), + self.TypeSpec.len(), + ]); + let has_constant = + metadata::coded_index_size(&[self.Field.len(), self.Param.len(), self.Property.len()]); + let type_or_method_def = + metadata::coded_index_size(&[self.TypeDef.len(), self.MethodDef.len()]); + let member_ref_parent = metadata::coded_index_size(&[ + self.TypeDef.len(), + self.TypeRef.len(), + self.ModuleRef.len(), + self.MethodDef.len(), + self.TypeSpec.len(), + ]); + let custom_attribute_type = + metadata::coded_index_size(&[self.MethodDef.len(), self.MemberRef.len(), 0, 0, 0]); + let has_custom_attribute = metadata::coded_index_size(&[ + self.MethodDef.len(), + self.Field.len(), + self.TypeRef.len(), + self.TypeDef.len(), + self.Param.len(), + self.InterfaceImpl.len(), + self.MemberRef.len(), + self.Module.len(), + 0, + 0, + 0, + self.ModuleRef.len(), + self.TypeSpec.len(), + 0, + self.AssemblyRef.len(), + 0, + 0, + 0, + self.GenericParam.len(), + 0, + 0, + ]); let valid_tables: u64 = 1 << 0 | // Module 1 << 0x01 | // TypeRef diff --git a/crates/libs/bindgen/src/winmd/writer/traits.rs b/crates/libs/bindgen/src/winmd/writer/traits.rs index 78df141b10..109b128939 100644 --- a/crates/libs/bindgen/src/winmd/writer/traits.rs +++ b/crates/libs/bindgen/src/winmd/writer/traits.rs @@ -13,7 +13,10 @@ pub trait Write { impl Write for Vec { unsafe fn write_header(&mut self, value: &T) { - self.extend_from_slice(std::slice::from_raw_parts(value as *const _ as _, core::mem::size_of::())); + self.extend_from_slice(std::slice::from_raw_parts( + value as *const _ as _, + core::mem::size_of::(), + )); } fn write_u8(&mut self, value: u8) { diff --git a/crates/libs/core/src/agile_reference.rs b/crates/libs/core/src/agile_reference.rs index 0e0ba2acae..30554e9781 100644 --- a/crates/libs/core/src/agile_reference.rs +++ b/crates/libs/core/src/agile_reference.rs @@ -13,7 +13,14 @@ impl AgileReference { // For example, > // https://github.com/rust-lang/rust/issues/92827 assert!(T::UNKNOWN); - unsafe { imp::RoGetAgileReference(imp::AGILEREFERENCE_DEFAULT, &T::IID, core::mem::transmute::<&T, &IUnknown>(object)).map(|reference| Self(reference, Default::default())) } + unsafe { + imp::RoGetAgileReference( + imp::AGILEREFERENCE_DEFAULT, + &T::IID, + core::mem::transmute::<&T, &IUnknown>(object), + ) + .map(|reference| Self(reference, Default::default())) + } } /// Retrieves a proxy to the target of the `AgileReference` object that may safely be used within any thread context in which get is called. diff --git a/crates/libs/core/src/array.rs b/crates/libs/core/src/array.rs index d4b875f675..1dca64f1be 100644 --- a/crates/libs/core/src/array.rs +++ b/crates/libs/core/src/array.rs @@ -8,7 +8,10 @@ pub struct Array> { impl> Default for Array { fn default() -> Self { - Array { data: core::ptr::null_mut(), len: 0 } + Array { + data: core::ptr::null_mut(), + len: 0, + } } } @@ -21,7 +24,9 @@ impl> Array { /// Creates an array of the given length with default values. pub fn with_len(len: usize) -> Self { assert!(len < u32::MAX as usize); - let bytes_amount = len.checked_mul(core::mem::size_of::()).expect("Attempted to allocate too large an Array"); + let bytes_amount = len + .checked_mul(core::mem::size_of::()) + .expect("Attempted to allocate too large an Array"); // WinRT arrays must be allocated with CoTaskMemAlloc. // SAFETY: the call to CoTaskMemAlloc is safe to perform @@ -159,7 +164,11 @@ pub struct ArrayProxy> { impl> ArrayProxy { pub fn from_raw_parts(data: *mut *mut T::Default, len: *mut u32) -> Self { - Self { data, len, temp: core::mem::ManuallyDrop::new(Array::new()) } + Self { + data, + len, + temp: core::mem::ManuallyDrop::new(Array::new()), + } } pub fn as_array(&mut self) -> &mut Array { diff --git a/crates/libs/core/src/com_object.rs b/crates/libs/core/src/com_object.rs index 00d80e7b3b..ede313071e 100644 --- a/crates/libs/core/src/com_object.rs +++ b/crates/libs/core/src/com_object.rs @@ -1,5 +1,6 @@ use crate::imp::Box; use crate::{AsImpl, IUnknown, IUnknownImpl, Interface, InterfaceRef}; +use core::any::Any; use core::borrow::Borrow; use core::ops::Deref; use core::ptr::NonNull; @@ -196,6 +197,28 @@ impl ComObject { I::from_raw(raw) } } + + /// This casts the given COM interface to [`&dyn Any`]. It returns a reference to the "outer" + /// object, e.g. `MyApp_Impl`, not the inner `MyApp` object. + /// + /// `T` must be a type that has been annotated with `#[implement]`; this is checked at + /// compile-time by the generic constraints of this method. However, note that the + /// returned `&dyn Any` refers to the _outer_ implementation object that was generated by + /// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type. + /// + /// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust + /// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`. + /// + /// The returned value is an owned (counted) reference; this function calls `AddRef` on the + /// underlying COM object. If you do not need an owned reference, then you can use the + /// [`Interface::cast_object_ref`] method instead, and avoid the cost of `AddRef` / `Release`. + pub fn cast_from(interface: &I) -> crate::Result + where + I: Interface, + T::Outer: Any + 'static + IUnknownImpl, + { + interface.cast_object() + } } impl Default for ComObject { diff --git a/crates/libs/core/src/event.rs b/crates/libs/core/src/event.rs index 01a8e14ab7..bb74f7ad8b 100644 --- a/crates/libs/core/src/event.rs +++ b/crates/libs/core/src/event.rs @@ -23,7 +23,11 @@ impl Default for Event { impl Event { /// Creates a new, empty `Event`. pub fn new() -> Self { - Self { delegates: Array::new(), swap: Mutex::default(), change: Mutex::default() } + Self { + delegates: Array::new(), + swap: Mutex::default(), + change: Mutex::default(), + } } /// Registers a delegate with the event object. @@ -102,7 +106,10 @@ impl Event { for delegate in lock_free_calls.as_slice() { if let Err(error) = delegate.call(&mut callback) { const RPC_E_SERVER_UNAVAILABLE: HRESULT = HRESULT(-2147023174); // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) - if matches!(error.code(), imp::RPC_E_DISCONNECTED | imp::JSCRIPT_E_CANTEXECUTE | RPC_E_SERVER_UNAVAILABLE) { + if matches!( + error.code(), + imp::RPC_E_DISCONNECTED | imp::JSCRIPT_E_CANTEXECUTE | RPC_E_SERVER_UNAVAILABLE + ) { self.remove(delegate.to_token())?; } } @@ -127,12 +134,20 @@ impl Default for Array { impl Array { /// Creates a new, empty `Array` with no capacity. fn new() -> Self { - Self { buffer: null_mut(), len: 0, _phantom: PhantomData } + Self { + buffer: null_mut(), + len: 0, + _phantom: PhantomData, + } } /// Creates a new, empty `Array` with the specified capacity. fn with_capacity(capacity: usize) -> Result { - Ok(Self { buffer: Buffer::new(capacity)?, len: 0, _phantom: PhantomData }) + Ok(Self { + buffer: Buffer::new(capacity)?, + len: 0, + _phantom: PhantomData, + }) } /// Swaps the contents of two `Array` objects. @@ -184,7 +199,11 @@ impl Clone for Array { if !self.is_empty() { unsafe { (*self.buffer).0.add_ref() }; } - Self { buffer: self.buffer, len: self.len, _phantom: PhantomData } + Self { + buffer: self.buffer, + len: self.len, + _phantom: PhantomData, + } } } diff --git a/crates/libs/core/src/guid.rs b/crates/libs/core/src/guid.rs index 2a17ff1ddc..78dc60a49d 100644 --- a/crates/libs/core/src/guid.rs +++ b/crates/libs/core/src/guid.rs @@ -28,27 +28,48 @@ impl GUID { /// Creates a `GUID` represented by the all-zero byte-pattern. pub const fn zeroed() -> Self { - Self { data1: 0, data2: 0, data3: 0, data4: [0, 0, 0, 0, 0, 0, 0, 0] } + Self { + data1: 0, + data2: 0, + data3: 0, + data4: [0, 0, 0, 0, 0, 0, 0, 0], + } } /// Creates a `GUID` with the given constant values. pub const fn from_values(data1: u32, data2: u16, data3: u16, data4: [u8; 8]) -> Self { - Self { data1, data2, data3, data4 } + Self { + data1, + data2, + data3, + data4, + } } /// Creates a `GUID` from a `u128` value. 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() } + 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(), + } } /// Converts a `GUID` to a `u128` value. pub const fn to_u128(&self) -> u128 { - ((self.data1 as u128) << 96) + ((self.data2 as u128) << 80) + ((self.data3 as u128) << 64) + u64::from_be_bytes(self.data4) as u128 + ((self.data1 as u128) << 96) + + ((self.data2 as u128) << 80) + + ((self.data3 as u128) << 64) + + u64::from_be_bytes(self.data4) as u128 } /// Creates a `GUID` for a "generic" WinRT type. pub const fn from_signature(signature: imp::ConstBuffer) -> Self { - let data = imp::ConstBuffer::from_slice(&[0x11, 0xf4, 0x7a, 0xd5, 0x7b, 0x73, 0x42, 0xc0, 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee]); + let data = imp::ConstBuffer::from_slice(&[ + 0x11, 0xf4, 0x7a, 0xd5, 0x7b, 0x73, 0x42, 0xc0, 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, + 0xad, 0xee, + ]); let data = data.push_other(signature); @@ -60,7 +81,14 @@ impl GUID { third = (third & 0x0fff) | (5 << 12); let fourth = (bytes[8] & 0x3f) | 0x80; - Self::from_values(first, second, third, [fourth, bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]]) + Self::from_values( + first, + second, + third, + [ + fourth, bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15], + ], + ) } } @@ -74,7 +102,21 @@ impl TypeKind for GUID { impl core::fmt::Debug for GUID { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{:08X?}-{:04X?}-{:04X?}-{:02X?}{:02X?}-{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}", self.data1, self.data2, self.data3, self.data4[0], self.data4[1], self.data4[2], self.data4[3], self.data4[4], self.data4[5], self.data4[6], self.data4[7]) + write!( + f, + "{:08X?}-{:04X?}-{:04X?}-{:02X?}{:02X?}-{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}", + self.data1, + self.data2, + self.data3, + self.data4[0], + self.data4[1], + self.data4[2], + self.data4[3], + self.data4[4], + self.data4[5], + self.data4[6], + self.data4[7] + ) } } @@ -83,11 +125,19 @@ impl From<&str> for GUID { assert!(value.len() == 36, "Invalid GUID string"); let mut bytes = value.bytes(); - let a = ((bytes.next_u32() * 16 + bytes.next_u32()) << 24) + ((bytes.next_u32() * 16 + bytes.next_u32()) << 16) + ((bytes.next_u32() * 16 + bytes.next_u32()) << 8) + bytes.next_u32() * 16 + bytes.next_u32(); + let a = ((bytes.next_u32() * 16 + bytes.next_u32()) << 24) + + ((bytes.next_u32() * 16 + bytes.next_u32()) << 16) + + ((bytes.next_u32() * 16 + bytes.next_u32()) << 8) + + bytes.next_u32() * 16 + + bytes.next_u32(); assert!(bytes.next().unwrap() == b'-', "Invalid GUID string"); - let b = ((bytes.next_u16() * 16 + (bytes.next_u16())) << 8) + bytes.next_u16() * 16 + bytes.next_u16(); + let b = ((bytes.next_u16() * 16 + (bytes.next_u16())) << 8) + + bytes.next_u16() * 16 + + bytes.next_u16(); assert!(bytes.next().unwrap() == b'-', "Invalid GUID string"); - let c = ((bytes.next_u16() * 16 + bytes.next_u16()) << 8) + bytes.next_u16() * 16 + bytes.next_u16(); + let c = ((bytes.next_u16() * 16 + bytes.next_u16()) << 8) + + bytes.next_u16() * 16 + + bytes.next_u16(); assert!(bytes.next().unwrap() == b'-', "Invalid GUID string"); let d = bytes.next_u8() * 16 + bytes.next_u8(); let e = bytes.next_u8() * 16 + bytes.next_u8(); diff --git a/crates/libs/core/src/imp/bindings.rs b/crates/libs/core/src/imp/bindings.rs index 40b910e0ac..0492583977 100644 --- a/crates/libs/core/src/imp/bindings.rs +++ b/crates/libs/core/src/imp/bindings.rs @@ -1,4 +1,10 @@ -#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] windows_targets::link!("api-ms-win-core-winrt-l1-1-0.dll" "system" fn RoGetActivationFactory(activatableclassid : * mut core::ffi::c_void, iid : *const GUID, factory : *mut *mut core::ffi::c_void) -> HRESULT); windows_targets::link!("kernel32.dll" "system" fn CloseHandle(hobject : HANDLE) -> BOOL); windows_targets::link!("kernel32.dll" "system" fn CreateEventW(lpeventattributes : *const SECURITY_ATTRIBUTES, bmanualreset : BOOL, binitialstate : BOOL, lpname : PCWSTR) -> HANDLE); @@ -325,7 +331,12 @@ pub struct GUID { } 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() } + 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(), + } } } pub type HANDLE = isize; @@ -343,7 +354,8 @@ pub type IMPLTYPEFLAGS = i32; pub type INVOKEKIND = i32; pub type LOAD_LIBRARY_FLAGS = u32; pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: LOAD_LIBRARY_FLAGS = 4096u32; -pub type LPEXCEPFINO_DEFERRED_FILLIN = Option HRESULT>; +pub type LPEXCEPFINO_DEFERRED_FILLIN = + Option HRESULT>; #[repr(C)] #[derive(Clone, Copy)] pub struct PARAMDESC { diff --git a/crates/libs/core/src/imp/com_bindings.rs b/crates/libs/core/src/imp/com_bindings.rs index 4c69f42375..169d6cae87 100644 --- a/crates/libs/core/src/imp/com_bindings.rs +++ b/crates/libs/core/src/imp/com_bindings.rs @@ -1,4 +1,10 @@ -#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] #[inline] pub unsafe fn CoCreateGuid() -> windows_core::Result { windows_targets::link!("ole32.dll" "system" fn CoCreateGuid(pguid : *mut windows_core::GUID) -> windows_core::HRESULT); @@ -6,13 +12,18 @@ pub unsafe fn CoCreateGuid() -> windows_core::Result { CoCreateGuid(&mut result__).map(|| result__) } #[inline] -pub unsafe fn RoGetAgileReference(options: AgileReferenceOptions, riid: *const windows_core::GUID, punk: P0) -> windows_core::Result +pub unsafe fn RoGetAgileReference( + options: AgileReferenceOptions, + riid: *const windows_core::GUID, + punk: P0, +) -> windows_core::Result where P0: windows_core::Param, { windows_targets::link!("ole32.dll" "system" fn RoGetAgileReference(options : AgileReferenceOptions, riid : *const windows_core::GUID, punk : * mut core::ffi::c_void, ppagilereference : *mut * mut core::ffi::c_void) -> windows_core::HRESULT); let mut result__ = core::mem::zeroed(); - RoGetAgileReference(options, riid, punk.param().abi(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + RoGetAgileReference(options, riid, punk.param().abi(), &mut result__) + .and_then(|| windows_core::Type::from_abi(result__)) } pub const AGILEREFERENCE_DEFAULT: AgileReferenceOptions = AgileReferenceOptions(0i32); #[repr(transparent)] @@ -23,7 +34,9 @@ impl windows_core::TypeKind for AgileReferenceOptions { } impl core::fmt::Debug for AgileReferenceOptions { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_tuple("AgileReferenceOptions").field(&self.0).finish() + f.debug_tuple("AgileReferenceOptions") + .field(&self.0) + .finish() } } pub const CO_E_NOTINITIALIZED: windows_core::HRESULT = windows_core::HRESULT(0x800401F0_u32 as _); @@ -36,7 +49,8 @@ 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)"); + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.DateTime;i8)"); } impl Default for DateTime { fn default() -> Self { @@ -47,7 +61,11 @@ pub const E_BOUNDS: windows_core::HRESULT = windows_core::HRESULT(0x8000000B_u32 pub const E_NOINTERFACE: windows_core::HRESULT = windows_core::HRESULT(0x80004002_u32 as _); pub const E_OUTOFMEMORY: windows_core::HRESULT = windows_core::HRESULT(0x8007000E_u32 as _); pub const E_POINTER: windows_core::HRESULT = windows_core::HRESULT(0x80004003_u32 as _); -windows_core::imp::define_interface!(IAgileObject, IAgileObject_Vtbl, 0x94ea2b94_e9cc_49e0_c0ff_ee64ca8f5b90); +windows_core::imp::define_interface!( + IAgileObject, + IAgileObject_Vtbl, + 0x94ea2b94_e9cc_49e0_c0ff_ee64ca8f5b90 +); impl core::ops::Deref for IAgileObject { type Target = windows_core::IUnknown; fn deref(&self) -> &Self::Target { @@ -60,7 +78,11 @@ impl IAgileObject {} pub struct IAgileObject_Vtbl { pub base__: windows_core::IUnknown_Vtbl, } -windows_core::imp::define_interface!(IAgileReference, IAgileReference_Vtbl, 0xc03f6a43_65a4_9818_987e_e0b810d2a6f2); +windows_core::imp::define_interface!( + IAgileReference, + IAgileReference_Vtbl, + 0xc03f6a43_65a4_9818_987e_e0b810d2a6f2 +); impl core::ops::Deref for IAgileReference { type Target = windows_core::IUnknown; fn deref(&self) -> &Self::Target { @@ -74,332 +96,865 @@ impl IAgileReference { T: windows_core::Interface, { let mut result__ = core::ptr::null_mut(); - (windows_core::Interface::vtable(self).Resolve)(windows_core::Interface::as_raw(self), &T::IID, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(self).Resolve)( + windows_core::Interface::as_raw(self), + &T::IID, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) } } #[repr(C)] pub struct IAgileReference_Vtbl { pub base__: windows_core::IUnknown_Vtbl, - pub Resolve: unsafe extern "system" fn(*mut core::ffi::c_void, *const windows_core::GUID, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, + pub Resolve: unsafe extern "system" fn( + *mut core::ffi::c_void, + *const windows_core::GUID, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, } -windows_core::imp::define_interface!(IPropertyValue, IPropertyValue_Vtbl, 0x4bd682dd_7554_40e9_9a9b_82654ede7e62); +windows_core::imp::define_interface!( + IPropertyValue, + IPropertyValue_Vtbl, + 0x4bd682dd_7554_40e9_9a9b_82654ede7e62 +); impl core::ops::Deref for IPropertyValue { type Target = windows_core::IInspectable; fn deref(&self) -> &Self::Target { unsafe { core::mem::transmute(self) } } } -windows_core::imp::interface_hierarchy!(IPropertyValue, windows_core::IUnknown, windows_core::IInspectable); +windows_core::imp::interface_hierarchy!( + IPropertyValue, + windows_core::IUnknown, + windows_core::IInspectable +); impl IPropertyValue { pub fn Type(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).Type)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).Type)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn IsNumericScalar(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).IsNumericScalar)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).IsNumericScalar)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt8(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetUInt8)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetUInt8)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetInt16(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetInt16)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetInt16)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt16(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetUInt16)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetUInt16)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetInt32(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetInt32)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetInt32)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt32(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetUInt32)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetUInt32)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetInt64(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetInt64)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetInt64)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt64(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetUInt64)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetUInt64)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetSingle(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetSingle)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetSingle)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetDouble(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetDouble)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetDouble)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetChar16(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetChar16)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetChar16)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetBoolean(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetBoolean)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetBoolean)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetString(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetString)(windows_core::Interface::as_raw(this), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).GetString)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) } } pub fn GetGuid(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetGuid)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetGuid)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetDateTime(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetDateTime)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetDateTime)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetTimeSpan(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetTimeSpan)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetTimeSpan)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetPoint(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetPoint)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetPoint)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetSize(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetSize)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetSize)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetRect(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetRect)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetRect)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt8Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetUInt8Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetUInt8Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetInt16Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetInt16Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetInt16Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetUInt16Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetUInt16Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetUInt16Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetInt32Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetInt32Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetInt32Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetUInt32Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetUInt32Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetUInt32Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetInt64Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetInt64Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetInt64Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetUInt64Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetUInt64Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetUInt64Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetSingleArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetSingleArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetSingleArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetDoubleArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetDoubleArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetDoubleArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetChar16Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetChar16Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetChar16Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetBooleanArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetBooleanArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetBooleanArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetBooleanArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetStringArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetStringArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetStringArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetStringArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetInspectableArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetInspectableArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetInspectableArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetInspectableArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetGuidArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetGuidArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetGuidArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetGuidArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetDateTimeArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetDateTimeArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetDateTimeArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetDateTimeArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetTimeSpanArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetTimeSpanArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetTimeSpanArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetTimeSpanArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetPointArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetPointArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetPointArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetPointArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetSizeArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetSizeArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetSizeArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetRectArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = self; - unsafe { (windows_core::Interface::vtable(this).GetRectArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetRectArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } } impl windows_core::RuntimeType for IPropertyValue { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::for_interface::(); + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); } #[repr(C)] pub struct IPropertyValue_Vtbl { pub base__: windows_core::IInspectable_Vtbl, - pub Type: unsafe extern "system" fn(*mut core::ffi::c_void, *mut PropertyType) -> windows_core::HRESULT, - pub IsNumericScalar: unsafe extern "system" fn(*mut core::ffi::c_void, *mut bool) -> windows_core::HRESULT, - pub GetUInt8: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u8) -> windows_core::HRESULT, - pub GetInt16: unsafe extern "system" fn(*mut core::ffi::c_void, *mut i16) -> windows_core::HRESULT, - pub GetUInt16: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u16) -> windows_core::HRESULT, - pub GetInt32: unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, - pub GetUInt32: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32) -> windows_core::HRESULT, - pub GetInt64: unsafe extern "system" fn(*mut core::ffi::c_void, *mut i64) -> windows_core::HRESULT, - pub GetUInt64: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u64) -> windows_core::HRESULT, - pub GetSingle: unsafe extern "system" fn(*mut core::ffi::c_void, *mut f32) -> windows_core::HRESULT, - pub GetDouble: unsafe extern "system" fn(*mut core::ffi::c_void, *mut f64) -> windows_core::HRESULT, - pub GetChar16: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u16) -> windows_core::HRESULT, - pub GetBoolean: unsafe extern "system" fn(*mut core::ffi::c_void, *mut bool) -> windows_core::HRESULT, - pub GetString: unsafe extern "system" fn(*mut core::ffi::c_void, *mut core::mem::MaybeUninit) -> windows_core::HRESULT, - pub GetGuid: unsafe extern "system" fn(*mut core::ffi::c_void, *mut windows_core::GUID) -> windows_core::HRESULT, - pub GetDateTime: unsafe extern "system" fn(*mut core::ffi::c_void, *mut DateTime) -> windows_core::HRESULT, - pub GetTimeSpan: unsafe extern "system" fn(*mut core::ffi::c_void, *mut TimeSpan) -> windows_core::HRESULT, - pub GetPoint: unsafe extern "system" fn(*mut core::ffi::c_void, *mut Point) -> windows_core::HRESULT, - pub GetSize: unsafe extern "system" fn(*mut core::ffi::c_void, *mut Size) -> windows_core::HRESULT, - pub GetRect: unsafe extern "system" fn(*mut core::ffi::c_void, *mut Rect) -> windows_core::HRESULT, - pub GetUInt8Array: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut u8) -> windows_core::HRESULT, - pub GetInt16Array: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut i16) -> windows_core::HRESULT, - pub GetUInt16Array: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut u16) -> windows_core::HRESULT, - pub GetInt32Array: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut i32) -> windows_core::HRESULT, - pub GetUInt32Array: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut u32) -> windows_core::HRESULT, - pub GetInt64Array: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut i64) -> windows_core::HRESULT, - pub GetUInt64Array: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut u64) -> windows_core::HRESULT, - pub GetSingleArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut f32) -> windows_core::HRESULT, - pub GetDoubleArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut f64) -> windows_core::HRESULT, - pub GetChar16Array: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut u16) -> windows_core::HRESULT, - pub GetBooleanArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut bool) -> windows_core::HRESULT, - pub GetStringArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut core::mem::MaybeUninit) -> windows_core::HRESULT, - pub GetInspectableArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub GetGuidArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut windows_core::GUID) -> windows_core::HRESULT, - pub GetDateTimeArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut DateTime) -> windows_core::HRESULT, - pub GetTimeSpanArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut TimeSpan) -> windows_core::HRESULT, - pub GetPointArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut Point) -> windows_core::HRESULT, - pub GetSizeArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut Size) -> windows_core::HRESULT, - pub GetRectArray: unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32, *mut *mut Rect) -> windows_core::HRESULT, + pub Type: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut PropertyType, + ) -> windows_core::HRESULT, + pub IsNumericScalar: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut bool) -> windows_core::HRESULT, + pub GetUInt8: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut u8) -> windows_core::HRESULT, + pub GetInt16: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut i16) -> windows_core::HRESULT, + pub GetUInt16: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut u16) -> windows_core::HRESULT, + pub GetInt32: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, + pub GetUInt32: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32) -> windows_core::HRESULT, + pub GetInt64: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut i64) -> windows_core::HRESULT, + pub GetUInt64: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut u64) -> windows_core::HRESULT, + pub GetSingle: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut f32) -> windows_core::HRESULT, + pub GetDouble: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut f64) -> windows_core::HRESULT, + pub GetChar16: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut u16) -> windows_core::HRESULT, + pub GetBoolean: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut bool) -> windows_core::HRESULT, + pub GetString: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::mem::MaybeUninit, + ) -> windows_core::HRESULT, + pub GetGuid: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut windows_core::GUID, + ) -> windows_core::HRESULT, + pub GetDateTime: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut DateTime) -> windows_core::HRESULT, + pub GetTimeSpan: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut TimeSpan) -> windows_core::HRESULT, + pub GetPoint: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut Point) -> windows_core::HRESULT, + pub GetSize: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut Size) -> windows_core::HRESULT, + pub GetRect: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut Rect) -> windows_core::HRESULT, + pub GetUInt8Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut u8, + ) -> windows_core::HRESULT, + pub GetInt16Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut i16, + ) -> windows_core::HRESULT, + pub GetUInt16Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut u16, + ) -> windows_core::HRESULT, + pub GetInt32Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut i32, + ) -> windows_core::HRESULT, + pub GetUInt32Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut u32, + ) -> windows_core::HRESULT, + pub GetInt64Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut i64, + ) -> windows_core::HRESULT, + pub GetUInt64Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut u64, + ) -> windows_core::HRESULT, + pub GetSingleArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut f32, + ) -> windows_core::HRESULT, + pub GetDoubleArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut f64, + ) -> windows_core::HRESULT, + pub GetChar16Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut u16, + ) -> windows_core::HRESULT, + pub GetBooleanArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut bool, + ) -> windows_core::HRESULT, + pub GetStringArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut core::mem::MaybeUninit, + ) -> windows_core::HRESULT, + pub GetInspectableArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub GetGuidArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut windows_core::GUID, + ) -> windows_core::HRESULT, + pub GetDateTimeArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut DateTime, + ) -> windows_core::HRESULT, + pub GetTimeSpanArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut TimeSpan, + ) -> windows_core::HRESULT, + pub GetPointArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut Point, + ) -> windows_core::HRESULT, + pub GetSizeArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut Size, + ) -> windows_core::HRESULT, + pub GetRectArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut u32, + *mut *mut Rect, + ) -> windows_core::HRESULT, } -windows_core::imp::define_interface!(IPropertyValueStatics, IPropertyValueStatics_Vtbl, 0x629bdbc8_d932_4ff4_96b9_8d96c5c1e858); +windows_core::imp::define_interface!( + IPropertyValueStatics, + IPropertyValueStatics_Vtbl, + 0x629bdbc8_d932_4ff4_96b9_8d96c5c1e858 +); impl windows_core::RuntimeType for IPropertyValueStatics { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::for_interface::(); + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); } #[repr(C)] pub struct IPropertyValueStatics_Vtbl { pub base__: windows_core::IInspectable_Vtbl, - pub CreateEmpty: unsafe extern "system" fn(*mut core::ffi::c_void, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateUInt8: unsafe extern "system" fn(*mut core::ffi::c_void, u8, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateInt16: unsafe extern "system" fn(*mut core::ffi::c_void, i16, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateUInt16: unsafe extern "system" fn(*mut core::ffi::c_void, u16, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateInt32: unsafe extern "system" fn(*mut core::ffi::c_void, i32, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateUInt32: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateInt64: unsafe extern "system" fn(*mut core::ffi::c_void, i64, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateUInt64: unsafe extern "system" fn(*mut core::ffi::c_void, u64, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateSingle: unsafe extern "system" fn(*mut core::ffi::c_void, f32, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateDouble: unsafe extern "system" fn(*mut core::ffi::c_void, f64, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateChar16: unsafe extern "system" fn(*mut core::ffi::c_void, u16, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateBoolean: unsafe extern "system" fn(*mut core::ffi::c_void, bool, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateString: unsafe extern "system" fn(*mut core::ffi::c_void, core::mem::MaybeUninit, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateInspectable: unsafe extern "system" fn(*mut core::ffi::c_void, *mut core::ffi::c_void, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateGuid: unsafe extern "system" fn(*mut core::ffi::c_void, windows_core::GUID, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateDateTime: unsafe extern "system" fn(*mut core::ffi::c_void, DateTime, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateTimeSpan: unsafe extern "system" fn(*mut core::ffi::c_void, TimeSpan, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreatePoint: unsafe extern "system" fn(*mut core::ffi::c_void, Point, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateSize: unsafe extern "system" fn(*mut core::ffi::c_void, Size, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateRect: unsafe extern "system" fn(*mut core::ffi::c_void, Rect, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateUInt8Array: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const u8, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateInt16Array: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const i16, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateUInt16Array: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const u16, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateInt32Array: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const i32, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateUInt32Array: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const u32, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateInt64Array: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const i64, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateUInt64Array: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const u64, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateSingleArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const f32, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateDoubleArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const f64, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateChar16Array: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const u16, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateBooleanArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const bool, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateStringArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const core::mem::MaybeUninit, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateInspectableArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const *mut core::ffi::c_void, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateGuidArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const windows_core::GUID, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateDateTimeArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const DateTime, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateTimeSpanArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const TimeSpan, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreatePointArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const Point, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateSizeArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const Size, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, - pub CreateRectArray: unsafe extern "system" fn(*mut core::ffi::c_void, u32, *const Rect, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, + pub CreateEmpty: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateUInt8: unsafe extern "system" fn( + *mut core::ffi::c_void, + u8, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateInt16: unsafe extern "system" fn( + *mut core::ffi::c_void, + i16, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateUInt16: unsafe extern "system" fn( + *mut core::ffi::c_void, + u16, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateInt32: unsafe extern "system" fn( + *mut core::ffi::c_void, + i32, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateUInt32: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateInt64: unsafe extern "system" fn( + *mut core::ffi::c_void, + i64, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateUInt64: unsafe extern "system" fn( + *mut core::ffi::c_void, + u64, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateSingle: unsafe extern "system" fn( + *mut core::ffi::c_void, + f32, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateDouble: unsafe extern "system" fn( + *mut core::ffi::c_void, + f64, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateChar16: unsafe extern "system" fn( + *mut core::ffi::c_void, + u16, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateBoolean: unsafe extern "system" fn( + *mut core::ffi::c_void, + bool, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateString: unsafe extern "system" fn( + *mut core::ffi::c_void, + core::mem::MaybeUninit, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateInspectable: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateGuid: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::GUID, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateDateTime: unsafe extern "system" fn( + *mut core::ffi::c_void, + DateTime, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateTimeSpan: unsafe extern "system" fn( + *mut core::ffi::c_void, + TimeSpan, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreatePoint: unsafe extern "system" fn( + *mut core::ffi::c_void, + Point, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateSize: unsafe extern "system" fn( + *mut core::ffi::c_void, + Size, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateRect: unsafe extern "system" fn( + *mut core::ffi::c_void, + Rect, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateUInt8Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const u8, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateInt16Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const i16, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateUInt16Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const u16, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateInt32Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const i32, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateUInt32Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const u32, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateInt64Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const i64, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateUInt64Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const u64, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateSingleArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const f32, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateDoubleArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const f64, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateChar16Array: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const u16, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateBooleanArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const bool, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateStringArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const core::mem::MaybeUninit, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateInspectableArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateGuidArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const windows_core::GUID, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateDateTimeArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const DateTime, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateTimeSpanArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const TimeSpan, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreatePointArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const Point, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateSizeArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const Size, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateRectArray: unsafe extern "system" fn( + *mut core::ffi::c_void, + u32, + *const Rect, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, } #[repr(transparent)] #[derive(PartialEq, Eq, core::fmt::Debug, Clone)] @@ -412,9 +967,17 @@ impl core::ops::Deref for IReference unsafe { core::mem::transmute(self) } } } -impl windows_core::imp::CanInto for IReference {} -impl windows_core::imp::CanInto for IReference {} -impl windows_core::imp::CanInto for IReference { +impl windows_core::imp::CanInto + for IReference +{ +} +impl windows_core::imp::CanInto + for IReference +{ +} +impl windows_core::imp::CanInto + for IReference +{ const QUERY: bool = true; } impl IReference { @@ -422,232 +985,478 @@ impl IReference { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).Value)(windows_core::Interface::as_raw(this), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).Value)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) } } pub fn Type(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).Type)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).Type)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn IsNumericScalar(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).IsNumericScalar)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).IsNumericScalar)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt8(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetUInt8)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetUInt8)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetInt16(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetInt16)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetInt16)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt16(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetUInt16)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetUInt16)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetInt32(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetInt32)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetInt32)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt32(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetUInt32)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetUInt32)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetInt64(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetInt64)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetInt64)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt64(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetUInt64)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetUInt64)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetSingle(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetSingle)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetSingle)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetDouble(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetDouble)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetDouble)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetChar16(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetChar16)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetChar16)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetBoolean(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetBoolean)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetBoolean)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetString(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetString)(windows_core::Interface::as_raw(this), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).GetString)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) } } pub fn GetGuid(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetGuid)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetGuid)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetDateTime(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetDateTime)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetDateTime)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetTimeSpan(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetTimeSpan)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetTimeSpan)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetPoint(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetPoint)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetPoint)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetSize(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetSize)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetSize)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetRect(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).GetRect)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + (windows_core::Interface::vtable(this).GetRect)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) } } pub fn GetUInt8Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetUInt8Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetUInt8Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetInt16Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetInt16Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetInt16Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetUInt16Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetUInt16Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetUInt16Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetInt32Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetInt32Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetInt32Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetUInt32Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetUInt32Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetUInt32Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetInt64Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetInt64Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetInt64Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetUInt64Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetUInt64Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetUInt64Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetSingleArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetSingleArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetSingleArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetDoubleArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetDoubleArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetDoubleArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetChar16Array(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetChar16Array)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetChar16Array)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetBooleanArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetBooleanArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetBooleanArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetBooleanArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetStringArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetStringArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetStringArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetStringArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetInspectableArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetInspectableArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetInspectableArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetInspectableArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetGuidArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetGuidArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetGuidArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetGuidArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetDateTimeArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetDateTimeArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetDateTimeArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetDateTimeArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetTimeSpanArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetTimeSpanArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetTimeSpanArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetTimeSpanArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } - pub fn GetPointArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { + pub fn GetPointArray( + &self, + value: &mut windows_core::Array, + ) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetPointArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetPointArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetSizeArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetSizeArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetSizeArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } pub fn GetRectArray(&self, value: &mut windows_core::Array) -> windows_core::Result<()> { let this = &windows_core::Interface::cast::(self)?; - unsafe { (windows_core::Interface::vtable(this).GetRectArray)(windows_core::Interface::as_raw(this), value.set_abi_len(), value as *mut _ as _).ok() } + unsafe { + (windows_core::Interface::vtable(this).GetRectArray)( + windows_core::Interface::as_raw(this), + value.set_abi_len(), + value as *mut _ as _, + ) + .ok() + } } } impl windows_core::RuntimeType for IReference { - const SIGNATURE: windows_core::imp::ConstBuffer = { windows_core::imp::ConstBuffer::new().push_slice(b"pinterface(").push_slice(b"{61c17706-2d65-11e0-9ae8-d48564015472}").push_slice(b";").push_other(T::SIGNATURE).push_slice(b")") }; + const SIGNATURE: windows_core::imp::ConstBuffer = { + windows_core::imp::ConstBuffer::new() + .push_slice(b"pinterface(") + .push_slice(b"{61c17706-2d65-11e0-9ae8-d48564015472}") + .push_slice(b";") + .push_other(T::SIGNATURE) + .push_slice(b")") + }; } unsafe impl windows_core::Interface for IReference { type Vtable = IReference_Vtbl; - const IID: windows_core::GUID = windows_core::GUID::from_signature(::SIGNATURE); + const IID: windows_core::GUID = + windows_core::GUID::from_signature(::SIGNATURE); } #[repr(C)] pub struct IReference_Vtbl @@ -655,35 +1464,58 @@ where T: windows_core::RuntimeType + 'static, { pub base__: windows_core::IInspectable_Vtbl, - pub Value: unsafe extern "system" fn(*mut core::ffi::c_void, *mut windows_core::AbiType) -> windows_core::HRESULT, + pub Value: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut windows_core::AbiType, + ) -> windows_core::HRESULT, pub T: core::marker::PhantomData, } -windows_core::imp::define_interface!(IStringable, IStringable_Vtbl, 0x96369f54_8eb6_48f0_abce_c1b211e627c3); +windows_core::imp::define_interface!( + IStringable, + IStringable_Vtbl, + 0x96369f54_8eb6_48f0_abce_c1b211e627c3 +); impl core::ops::Deref for IStringable { type Target = windows_core::IInspectable; fn deref(&self) -> &Self::Target { unsafe { core::mem::transmute(self) } } } -windows_core::imp::interface_hierarchy!(IStringable, windows_core::IUnknown, windows_core::IInspectable); +windows_core::imp::interface_hierarchy!( + IStringable, + windows_core::IUnknown, + windows_core::IInspectable +); impl IStringable { pub fn ToString(&self) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).ToString)(windows_core::Interface::as_raw(this), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).ToString)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) } } } impl windows_core::RuntimeType for IStringable { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::for_interface::(); + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); } #[repr(C)] pub struct IStringable_Vtbl { pub base__: windows_core::IInspectable_Vtbl, - pub ToString: unsafe extern "system" fn(*mut core::ffi::c_void, *mut core::mem::MaybeUninit) -> windows_core::HRESULT, + pub ToString: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::mem::MaybeUninit, + ) -> windows_core::HRESULT, } -windows_core::imp::define_interface!(IWeakReference, IWeakReference_Vtbl, 0x00000037_0000_0000_c000_000000000046); +windows_core::imp::define_interface!( + IWeakReference, + IWeakReference_Vtbl, + 0x00000037_0000_0000_c000_000000000046 +); impl core::ops::Deref for IWeakReference { type Target = windows_core::IUnknown; fn deref(&self) -> &Self::Target { @@ -697,15 +1529,28 @@ impl IWeakReference { T: windows_core::Interface, { let mut result__ = core::ptr::null_mut(); - (windows_core::Interface::vtable(self).Resolve)(windows_core::Interface::as_raw(self), &T::IID, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(self).Resolve)( + windows_core::Interface::as_raw(self), + &T::IID, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) } } #[repr(C)] pub struct IWeakReference_Vtbl { pub base__: windows_core::IUnknown_Vtbl, - pub Resolve: unsafe extern "system" fn(*mut core::ffi::c_void, *const windows_core::GUID, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, + pub Resolve: unsafe extern "system" fn( + *mut core::ffi::c_void, + *const windows_core::GUID, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, } -windows_core::imp::define_interface!(IWeakReferenceSource, IWeakReferenceSource_Vtbl, 0x00000038_0000_0000_c000_000000000046); +windows_core::imp::define_interface!( + IWeakReferenceSource, + IWeakReferenceSource_Vtbl, + 0x00000038_0000_0000_c000_000000000046 +); impl core::ops::Deref for IWeakReferenceSource { type Target = windows_core::IUnknown; fn deref(&self) -> &Self::Target { @@ -716,13 +1561,20 @@ windows_core::imp::interface_hierarchy!(IWeakReferenceSource, windows_core::IUnk impl IWeakReferenceSource { pub unsafe fn GetWeakReference(&self) -> windows_core::Result { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(self).GetWeakReference)(windows_core::Interface::as_raw(self), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(self).GetWeakReference)( + windows_core::Interface::as_raw(self), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) } } #[repr(C)] pub struct IWeakReferenceSource_Vtbl { pub base__: windows_core::IUnknown_Vtbl, - pub GetWeakReference: unsafe extern "system" fn(*mut core::ffi::c_void, *mut *mut core::ffi::c_void) -> windows_core::HRESULT, + pub GetWeakReference: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, } pub const JSCRIPT_E_CANTEXECUTE: windows_core::HRESULT = windows_core::HRESULT(0x89020001_u32 as _); #[repr(C)] @@ -735,7 +1587,8 @@ impl windows_core::TypeKind for Point { type TypeKind = windows_core::CopyType; } impl windows_core::RuntimeType for Point { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.Point;f4;f4)"); + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.Point;f4;f4)"); } impl Default for Point { fn default() -> Self { @@ -797,86 +1650,153 @@ impl core::fmt::Debug for PropertyType { } } impl windows_core::RuntimeType for PropertyType { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::from_slice(b"enum(Windows.Foundation.PropertyType;i4)"); + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::from_slice(b"enum(Windows.Foundation.PropertyType;i4)"); } pub struct PropertyValue; impl PropertyValue { pub fn CreateEmpty() -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateEmpty)(windows_core::Interface::as_raw(this), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateEmpty)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateUInt8(value: u8) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateUInt8)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateUInt8)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateInt16(value: i16) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateInt16)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateInt16)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateUInt16(value: u16) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateUInt16)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateUInt16)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateInt32(value: i32) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateInt32)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateInt32)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateUInt32(value: u32) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateUInt32)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateUInt32)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateInt64(value: i64) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateInt64)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateInt64)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateUInt64(value: u64) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateUInt64)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateUInt64)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateSingle(value: f32) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateSingle)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateSingle)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateDouble(value: f64) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateDouble)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateDouble)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateChar16(value: u16) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateChar16)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateChar16)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateBoolean(value: bool) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateBoolean)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateBoolean)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } - pub fn CreateString(value: &windows_core::HSTRING) -> windows_core::Result { + pub fn CreateString( + value: &windows_core::HSTRING, + ) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateString)(windows_core::Interface::as_raw(this), core::mem::transmute_copy(value), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateString)( + windows_core::Interface::as_raw(this), + core::mem::transmute_copy(value), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateInspectable(value: P0) -> windows_core::Result @@ -885,162 +1805,329 @@ impl PropertyValue { { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateInspectable)(windows_core::Interface::as_raw(this), value.param().abi(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateInspectable)( + windows_core::Interface::as_raw(this), + value.param().abi(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } - pub fn CreateGuid(value: windows_core::GUID) -> windows_core::Result { + pub fn CreateGuid( + value: windows_core::GUID, + ) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateGuid)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateGuid)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateDateTime(value: DateTime) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateDateTime)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateDateTime)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateTimeSpan(value: TimeSpan) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateTimeSpan)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateTimeSpan)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreatePoint(value: Point) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreatePoint)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreatePoint)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateSize(value: Size) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateSize)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateSize)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateRect(value: Rect) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateRect)(windows_core::Interface::as_raw(this), value, &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateRect)( + windows_core::Interface::as_raw(this), + value, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateUInt8Array(value: &[u8]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateUInt8Array)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateUInt8Array)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateInt16Array(value: &[i16]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateInt16Array)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateInt16Array)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateUInt16Array(value: &[u16]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateUInt16Array)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateUInt16Array)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateInt32Array(value: &[i32]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateInt32Array)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateInt32Array)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateUInt32Array(value: &[u32]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateUInt32Array)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateUInt32Array)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateInt64Array(value: &[i64]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateInt64Array)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateInt64Array)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateUInt64Array(value: &[u64]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateUInt64Array)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateUInt64Array)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateSingleArray(value: &[f32]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateSingleArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateSingleArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateDoubleArray(value: &[f64]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateDoubleArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateDoubleArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateChar16Array(value: &[u16]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateChar16Array)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateChar16Array)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateBooleanArray(value: &[bool]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateBooleanArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateBooleanArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } - pub fn CreateStringArray(value: &[windows_core::HSTRING]) -> windows_core::Result { + pub fn CreateStringArray( + value: &[windows_core::HSTRING], + ) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateStringArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), core::mem::transmute(value.as_ptr()), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateStringArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + core::mem::transmute(value.as_ptr()), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } - pub fn CreateInspectableArray(value: &[Option]) -> windows_core::Result { + pub fn CreateInspectableArray( + value: &[Option], + ) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateInspectableArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), core::mem::transmute(value.as_ptr()), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateInspectableArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + core::mem::transmute(value.as_ptr()), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } - pub fn CreateGuidArray(value: &[windows_core::GUID]) -> windows_core::Result { + pub fn CreateGuidArray( + value: &[windows_core::GUID], + ) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateGuidArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateGuidArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } - pub fn CreateDateTimeArray(value: &[DateTime]) -> windows_core::Result { + pub fn CreateDateTimeArray( + value: &[DateTime], + ) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateDateTimeArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateDateTimeArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } - pub fn CreateTimeSpanArray(value: &[TimeSpan]) -> windows_core::Result { + pub fn CreateTimeSpanArray( + value: &[TimeSpan], + ) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateTimeSpanArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateTimeSpanArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreatePointArray(value: &[Point]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreatePointArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreatePointArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateSizeArray(value: &[Size]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateSizeArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateSizeArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } pub fn CreateRectArray(value: &[Rect]) -> windows_core::Result { Self::IPropertyValueStatics(|this| unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).CreateRectArray)(windows_core::Interface::as_raw(this), value.len().try_into().unwrap(), value.as_ptr(), &mut result__).and_then(|| windows_core::Type::from_abi(result__)) + (windows_core::Interface::vtable(this).CreateRectArray)( + windows_core::Interface::as_raw(this), + value.len().try_into().unwrap(), + value.as_ptr(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) }) } #[doc(hidden)] - pub fn IPropertyValueStatics windows_core::Result>(callback: F) -> windows_core::Result { - static SHARED: windows_core::imp::FactoryCache = windows_core::imp::FactoryCache::new(); + pub fn IPropertyValueStatics< + R, + F: FnOnce(&IPropertyValueStatics) -> windows_core::Result, + >( + callback: F, + ) -> windows_core::Result { + static SHARED: windows_core::imp::FactoryCache = + windows_core::imp::FactoryCache::new(); SHARED.call(callback) } } @@ -1060,7 +2147,8 @@ impl windows_core::TypeKind for Rect { type TypeKind = windows_core::CopyType; } impl windows_core::RuntimeType for Rect { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.Rect;f4;f4;f4;f4)"); + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.Rect;f4;f4;f4;f4)"); } impl Default for Rect { fn default() -> Self { @@ -1077,7 +2165,8 @@ impl windows_core::TypeKind for Size { type TypeKind = windows_core::CopyType; } impl windows_core::RuntimeType for Size { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.Size;f4;f4)"); + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.Size;f4;f4)"); } impl Default for Size { fn default() -> Self { @@ -1094,7 +2183,8 @@ impl windows_core::TypeKind for TimeSpan { type TypeKind = windows_core::CopyType; } impl windows_core::RuntimeType for TimeSpan { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.TimeSpan;i8)"); + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::from_slice(b"struct(Windows.Foundation.TimeSpan;i8)"); } impl Default for TimeSpan { fn default() -> Self { diff --git a/crates/libs/core/src/imp/factory_cache.rs b/crates/libs/core/src/imp/factory_cache.rs index d6ee255e50..a6888291a0 100644 --- a/crates/libs/core/src/imp/factory_cache.rs +++ b/crates/libs/core/src/imp/factory_cache.rs @@ -15,7 +15,11 @@ pub struct FactoryCache { impl FactoryCache { pub const fn new() -> Self { - Self { shared: AtomicPtr::new(null_mut()), _c: PhantomData, _i: PhantomData } + Self { + shared: AtomicPtr::new(null_mut()), + _c: PhantomData, + _i: PhantomData, + } } } @@ -41,7 +45,16 @@ impl FactoryCache { // If the factory is agile, we can safely cache it. if factory.cast::().is_ok() { - if self.shared.compare_exchange_weak(null_mut(), factory.as_raw(), Ordering::Relaxed, Ordering::Relaxed).is_ok() { + if self + .shared + .compare_exchange_weak( + null_mut(), + factory.as_raw(), + Ordering::Relaxed, + Ordering::Relaxed, + ) + .is_ok() + { forget(factory); } } else { @@ -63,7 +76,13 @@ pub fn factory() -> crate::Result { let name = crate::HSTRING::from(C::NAME); let code = unsafe { - let mut get_com_factory = || crate::HRESULT(RoGetActivationFactory(transmute_copy(&name), &I::IID as *const _ as _, &mut factory as *mut _ as *mut _)); + let mut get_com_factory = || { + crate::HRESULT(RoGetActivationFactory( + transmute_copy(&name), + &I::IID as *const _ as _, + &mut factory as *mut _ as *mut _, + )) + }; let mut code = get_com_factory(); // If RoGetActivationFactory fails because combase hasn't been loaded yet then load combase @@ -89,7 +108,9 @@ pub fn factory() -> crate::Result { let original: crate::Error = code.into(); // Now attempt to find the factory's implementation heuristically. - if let Some(i) = search_path(C::NAME, |library| unsafe { get_activation_factory(library, &name) }) { + if let Some(i) = search_path(C::NAME, |library| unsafe { + get_activation_factory(library, &name) + }) { i.cast() } else { Err(original) @@ -122,13 +143,19 @@ where None } -unsafe fn get_activation_factory(library: crate::PCSTR, name: &crate::HSTRING) -> crate::Result { - let function = delay_load::(library, crate::s!("DllGetActivationFactory")).ok_or_else(crate::Error::from_win32)?; +unsafe fn get_activation_factory( + library: crate::PCSTR, + name: &crate::HSTRING, +) -> crate::Result { + let function = + delay_load::(library, crate::s!("DllGetActivationFactory")) + .ok_or_else(crate::Error::from_win32)?; let mut abi = null_mut(); function(transmute_copy(name), &mut abi).and_then(|| crate::Type::from_abi(abi)) } -type DllGetActivationFactory = extern "system" fn(name: *mut c_void, factory: *mut *mut c_void) -> crate::HRESULT; +type DllGetActivationFactory = + extern "system" fn(name: *mut c_void, factory: *mut *mut c_void) -> crate::HRESULT; #[cfg(test)] mod tests { diff --git a/crates/libs/core/src/imp/generic_factory.rs b/crates/libs/core/src/imp/generic_factory.rs index 75e9a58bcc..1f9ddcee5d 100644 --- a/crates/libs/core/src/imp/generic_factory.rs +++ b/crates/libs/core/src/imp/generic_factory.rs @@ -4,14 +4,23 @@ use core::mem::{transmute_copy, zeroed}; // A streamlined version of the IActivationFactory interface used by WinRT class factories used internally by the windows crate // to simplify code generation. Components should implement the `IActivationFactory` interface published by the windows crate. -super::define_interface!(IGenericFactory, IGenericFactory_Vtbl, 0x00000035_0000_0000_c000_000000000046); +super::define_interface!( + IGenericFactory, + IGenericFactory_Vtbl, + 0x00000035_0000_0000_c000_000000000046 +); super::interface_hierarchy!(IGenericFactory, crate::IUnknown, crate::IInspectable); impl IGenericFactory { pub fn ActivateInstance(&self) -> crate::Result { unsafe { let mut result__ = zeroed(); - (Interface::vtable(self).ActivateInstance)(transmute_copy(self), &mut result__ as *mut _ as *mut _).and_then(|| crate::Type::from_abi(result__)).and_then(|interface: crate::IInspectable| interface.cast()) + (Interface::vtable(self).ActivateInstance)( + transmute_copy(self), + &mut result__ as *mut _ as *mut _, + ) + .and_then(|| crate::Type::from_abi(result__)) + .and_then(|interface: crate::IInspectable| interface.cast()) } } } @@ -19,5 +28,6 @@ impl IGenericFactory { #[repr(C)] pub struct IGenericFactory_Vtbl { pub base__: crate::IInspectable_Vtbl, - pub ActivateInstance: unsafe extern "system" fn(this: *mut c_void, instance: *mut *mut c_void) -> crate::HRESULT, + pub ActivateInstance: + unsafe extern "system" fn(this: *mut c_void, instance: *mut *mut c_void) -> crate::HRESULT, } diff --git a/crates/libs/core/src/imp/mod.rs b/crates/libs/core/src/imp/mod.rs index be219aee6a..fbafcad084 100644 --- a/crates/libs/core/src/imp/mod.rs +++ b/crates/libs/core/src/imp/mod.rs @@ -77,22 +77,34 @@ pub use required_hierarchy; macro_rules! define_interface { ($name:ident, $vtbl:ident, $iid:literal) => { #[repr(transparent)] - #[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)] + #[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::clone::Clone)] pub struct $name(::windows_core::IUnknown); unsafe impl ::windows_core::Interface for $name { type Vtable = $vtbl; const IID: ::windows_core::GUID = ::windows_core::GUID::from_u128($iid); } + impl ::core::fmt::Debug for $name { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple(stringify!($name)) + .field(&::windows_core::Interface::as_raw(self)) + .finish() + } + } }; ($name:ident, $vtbl:ident) => { #[repr(transparent)] - #[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)] + #[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::clone::Clone)] pub struct $name(::std::ptr::NonNull<::std::ffi::c_void>); unsafe impl ::windows_core::Interface for $name { type Vtable = $vtbl; const IID: ::windows_core::GUID = ::windows_core::GUID::zeroed(); const UNKNOWN: bool = false; } + impl ::core::fmt::Debug for $name { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple(stringify!($name)).field(&self.0).finish() + } + } }; } diff --git a/crates/libs/core/src/imp/sha1.rs b/crates/libs/core/src/imp/sha1.rs index 56f1e323ce..92e6bb8be9 100644 --- a/crates/libs/core/src/imp/sha1.rs +++ b/crates/libs/core/src/imp/sha1.rs @@ -3,7 +3,10 @@ pub const fn sha1(data: &ConstBuffer) -> Digest { let state: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; let len: u64 = 0; - let blocks = Blocks { len: 0, data: [0; 64] }; + let blocks = Blocks { + len: 0, + data: [0; 64], + }; let (blocks, len, state) = process_blocks(blocks, data, len, state); digest(state, len, blocks) } @@ -17,7 +20,12 @@ pub struct ConstBuffer { impl ConstBuffer { pub const fn for_class() -> Self { - Self::new().push_slice(b"rc(").push_slice(C::NAME.as_bytes()).push(b';').push_other(I::SIGNATURE).push(b')') + Self::new() + .push_slice(b"rc(") + .push_slice(C::NAME.as_bytes()) + .push(b';') + .push_other(I::SIGNATURE) + .push(b')') } pub const fn for_interface() -> Self { @@ -30,7 +38,10 @@ impl ConstBuffer { } pub const fn new() -> Self { - Self { data: [0; BUFFER_SIZE], head: 0 } + Self { + data: [0; BUFFER_SIZE], + head: 0, + } } pub const fn push_slice(self, slice: &[u8]) -> Self { @@ -74,11 +85,13 @@ impl ConstBuffer { } const fn push_hex_u16(self, value: u16) -> Self { - self.push_hex_u8((value >> 8) as u8).push_hex_u8((value & 0xFF) as u8) + self.push_hex_u8((value >> 8) as u8) + .push_hex_u8((value & 0xFF) as u8) } const fn push_hex_u32(self, value: u32) -> Self { - self.push_hex_u16((value >> 16) as u16).push_hex_u16((value & 0xFFFF) as u16) + self.push_hex_u16((value >> 16) as u16) + .push_hex_u16((value & 0xFFFF) as u16) } const fn push_amount(mut self, slice: &[u8], amount: usize) -> Self { @@ -92,7 +105,19 @@ impl ConstBuffer { } const fn push_guid(self, guid: &crate::GUID) -> Self { - self.push(b'{').push_hex_u32(guid.data1).push(b'-').push_hex_u16(guid.data2).push(b'-').push_hex_u16(guid.data3).push(b'-').push_hex_u16((guid.data4[0] as u16) << 8 | guid.data4[1] as u16).push(b'-').push_hex_u16((guid.data4[2] as u16) << 8 | guid.data4[3] as u16).push_hex_u16((guid.data4[4] as u16) << 8 | guid.data4[5] as u16).push_hex_u16((guid.data4[6] as u16) << 8 | guid.data4[7] as u16).push(b'}') + self.push(b'{') + .push_hex_u32(guid.data1) + .push(b'-') + .push_hex_u16(guid.data2) + .push(b'-') + .push_hex_u16(guid.data3) + .push(b'-') + .push_hex_u16((guid.data4[0] as u16) << 8 | guid.data4[1] as u16) + .push(b'-') + .push_hex_u16((guid.data4[2] as u16) << 8 | guid.data4[3] as u16) + .push_hex_u16((guid.data4[4] as u16) << 8 | guid.data4[5] as u16) + .push_hex_u16((guid.data4[6] as u16) << 8 | guid.data4[7] as u16) + .push(b'}') } } @@ -101,20 +126,33 @@ struct Blocks { data: [u8; 64], } -const fn process_blocks(mut blocks: Blocks, data: &ConstBuffer, mut len: u64, mut state: [u32; 5]) -> (Blocks, u64, [u32; 5]) { +const fn process_blocks( + mut blocks: Blocks, + data: &ConstBuffer, + mut len: u64, + mut state: [u32; 5], +) -> (Blocks, u64, [u32; 5]) { const fn as_block(input: &ConstBuffer, offset: usize) -> [u32; 16] { let mut result = [0u32; 16]; let mut i = 0; while i != 16 { let off = offset + (i * 4); - result[i] = (input.get(off + 3) as u32) | ((input.get(off + 2) as u32) << 8) | ((input.get(off + 1) as u32) << 16) | ((input.get(off) as u32) << 24); + result[i] = (input.get(off + 3) as u32) + | ((input.get(off + 2) as u32) << 8) + | ((input.get(off + 1) as u32) << 16) + | ((input.get(off) as u32) << 24); i += 1; } result } - const fn clone_from_slice_64(mut data: [u8; 64], slice: &[u8], offset: usize, num_elems: usize) -> [u8; 64] { + const fn clone_from_slice_64( + mut data: [u8; 64], + slice: &[u8], + offset: usize, + num_elems: usize, + ) -> [u8; 64] { let mut i = 0; while i < num_elems { data[i] = slice[offset + i]; @@ -236,7 +274,12 @@ const fn process_state(mut state: [u32; 5], block: [u32; 16]) -> [u32; 5] { } const fn digest(mut state: [u32; 5], len: u64, blocks: Blocks) -> Digest { - const fn clone_from_slice_128(mut data: [u8; 128], slice: &[u8], offset: usize, num_elems: usize) -> [u8; 128] { + const fn clone_from_slice_128( + mut data: [u8; 128], + slice: &[u8], + offset: usize, + num_elems: usize, + ) -> [u8; 128] { let mut i = 0; while i < num_elems { data[i] = slice[offset + i]; @@ -260,14 +303,26 @@ const fn digest(mut state: [u32; 5], len: u64, blocks: Blocks) -> Digest { let mut i = 0; while i != 16 { let off = offset + (i * 4); - result[i] = (input[off + 3] as u32) | ((input[off + 2] as u32) << 8) | ((input[off + 1] as u32) << 16) | ((input[off] as u32) << 24); + result[i] = (input[off + 3] as u32) + | ((input[off + 2] as u32) << 8) + | ((input[off + 1] as u32) << 16) + | ((input[off] as u32) << 24); i += 1; } result } let bits = (len + (blocks.len as u64)) * 8; - let extra = [(bits >> 56) as u8, (bits >> 48) as u8, (bits >> 40) as u8, (bits >> 32) as u8, (bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]; + let extra = [ + (bits >> 56) as u8, + (bits >> 48) as u8, + (bits >> 40) as u8, + (bits >> 32) as u8, + (bits >> 24) as u8, + (bits >> 16) as u8, + (bits >> 8) as u8, + bits as u8, + ]; let mut last = [0; 128]; let blocklen = blocks.len as usize; last = clone_from_slice_128(last, &blocks.data, 0, blocklen); @@ -293,40 +348,95 @@ const fn blk(block: &[u32], i: usize) -> u32 { rol(value, 1) } -const fn r0(block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) { - let n = ((w & (x ^ y)) ^ y).wrapping_add(block[i]).wrapping_add(0x5a82_7999).wrapping_add(rol(v, 5)); +const fn r0( + block: [u32; 16], + v: u32, + mut w: u32, + x: u32, + y: u32, + mut z: u32, + i: usize, +) -> ([u32; 16], u32, u32) { + let n = ((w & (x ^ y)) ^ y) + .wrapping_add(block[i]) + .wrapping_add(0x5a82_7999) + .wrapping_add(rol(v, 5)); z = z.wrapping_add(n); w = rol(w, 30); (block, w, z) } -const fn r1(mut block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) { +const fn r1( + mut block: [u32; 16], + v: u32, + mut w: u32, + x: u32, + y: u32, + mut z: u32, + i: usize, +) -> ([u32; 16], u32, u32) { block[i] = blk(&block, i); - let n = ((w & (x ^ y)) ^ y).wrapping_add(block[i]).wrapping_add(0x5a82_7999).wrapping_add(rol(v, 5)); + let n = ((w & (x ^ y)) ^ y) + .wrapping_add(block[i]) + .wrapping_add(0x5a82_7999) + .wrapping_add(rol(v, 5)); z = z.wrapping_add(n); w = rol(w, 30); (block, w, z) } -const fn r2(mut block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) { +const fn r2( + mut block: [u32; 16], + v: u32, + mut w: u32, + x: u32, + y: u32, + mut z: u32, + i: usize, +) -> ([u32; 16], u32, u32) { block[i] = blk(&block, i); - let n = (w ^ x ^ y).wrapping_add(block[i]).wrapping_add(0x6ed9_eba1).wrapping_add(rol(v, 5)); + let n = (w ^ x ^ y) + .wrapping_add(block[i]) + .wrapping_add(0x6ed9_eba1) + .wrapping_add(rol(v, 5)); z = z.wrapping_add(n); w = rol(w, 30); (block, w, z) } -const fn r3(mut block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) { +const fn r3( + mut block: [u32; 16], + v: u32, + mut w: u32, + x: u32, + y: u32, + mut z: u32, + i: usize, +) -> ([u32; 16], u32, u32) { block[i] = blk(&block, i); - let n = (((w | x) & y) | (w & x)).wrapping_add(block[i]).wrapping_add(0x8f1b_bcdc).wrapping_add(rol(v, 5)); + let n = (((w | x) & y) | (w & x)) + .wrapping_add(block[i]) + .wrapping_add(0x8f1b_bcdc) + .wrapping_add(rol(v, 5)); z = z.wrapping_add(n); w = rol(w, 30); (block, w, z) } -const fn r4(mut block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) { +const fn r4( + mut block: [u32; 16], + v: u32, + mut w: u32, + x: u32, + y: u32, + mut z: u32, + i: usize, +) -> ([u32; 16], u32, u32) { block[i] = blk(&block, i); - let n = (w ^ x ^ y).wrapping_add(block[i]).wrapping_add(0xca62_c1d6).wrapping_add(rol(v, 5)); + let n = (w ^ x ^ y) + .wrapping_add(block[i]) + .wrapping_add(0xca62_c1d6) + .wrapping_add(rol(v, 5)); z = z.wrapping_add(n); w = rol(w, 30); (block, w, z) diff --git a/crates/libs/core/src/imp/weak_ref_count.rs b/crates/libs/core/src/imp/weak_ref_count.rs index 2bd3a2b9df..92fcf67313 100644 --- a/crates/libs/core/src/imp/weak_ref_count.rs +++ b/crates/libs/core/src/imp/weak_ref_count.rs @@ -16,7 +16,12 @@ impl WeakRefCount { } pub fn add_ref(&self) -> u32 { - self.0.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |count_or_pointer| bool::then_some(!is_weak_ref(count_or_pointer), count_or_pointer + 1)).map(|u| u as u32 + 1).unwrap_or_else(|pointer| unsafe { TearOff::decode(pointer).strong_count.add_ref() }) + self.0 + .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |count_or_pointer| { + bool::then_some(!is_weak_ref(count_or_pointer), count_or_pointer + 1) + }) + .map(|u| u as u32 + 1) + .unwrap_or_else(|pointer| unsafe { TearOff::decode(pointer).strong_count.add_ref() }) } #[inline(always)] @@ -25,18 +30,23 @@ impl WeakRefCount { } pub fn release(&self) -> u32 { - self.0.fetch_update(Ordering::Release, Ordering::Relaxed, |count_or_pointer| bool::then_some(!is_weak_ref(count_or_pointer), count_or_pointer - 1)).map(|u| u as u32 - 1).unwrap_or_else(|pointer| unsafe { - let tear_off = TearOff::decode(pointer); - let remaining = tear_off.strong_count.release(); - - // If this is the last strong reference, we can release the weak reference implied by the strong reference. - // There may still be weak references, so the WeakRelease is called to handle such possibilities. - if remaining == 0 { - TearOff::WeakRelease(&mut tear_off.weak_vtable as *mut _ as _); - } + self.0 + .fetch_update(Ordering::Release, Ordering::Relaxed, |count_or_pointer| { + bool::then_some(!is_weak_ref(count_or_pointer), count_or_pointer - 1) + }) + .map(|u| u as u32 - 1) + .unwrap_or_else(|pointer| unsafe { + let tear_off = TearOff::decode(pointer); + let remaining = tear_off.strong_count.release(); + + // If this is the last strong reference, we can release the weak reference implied by the strong reference. + // There may still be weak references, so the WeakRelease is called to handle such possibilities. + if remaining == 0 { + TearOff::WeakRelease(&mut tear_off.weak_vtable as *mut _ as _); + } - remaining - }) + remaining + }) } /// # Safety @@ -53,10 +63,16 @@ impl WeakRefCount { let tear_off = TearOff::new(object, count_or_pointer as u32); let tear_off_ptr: *mut c_void = transmute_copy(&tear_off); - let encoding: usize = ((tear_off_ptr as usize) >> 1) | (1 << (core::mem::size_of::() * 8 - 1)); + let encoding: usize = + ((tear_off_ptr as usize) >> 1) | (1 << (core::mem::size_of::() * 8 - 1)); loop { - match self.0.compare_exchange_weak(count_or_pointer, encoding as isize, Ordering::AcqRel, Ordering::Relaxed) { + match self.0.compare_exchange_weak( + count_or_pointer, + encoding as isize, + Ordering::AcqRel, + Ordering::Relaxed, + ) { Ok(_) => { let result: *mut c_void = transmute(tear_off); TearOff::from_strong_ptr(result).strong_count.add_ref(); @@ -69,7 +85,10 @@ impl WeakRefCount { return TearOff::from_encoding(count_or_pointer); } - TearOff::from_strong_ptr(tear_off_ptr).strong_count.0.store(count_or_pointer as i32, Ordering::SeqCst); + TearOff::from_strong_ptr(tear_off_ptr) + .strong_count + .0 + .store(count_or_pointer as i32, Ordering::SeqCst); } } } @@ -106,12 +125,20 @@ impl TearOff { } const STRONG_VTABLE: IWeakReferenceSource_Vtbl = IWeakReferenceSource_Vtbl { - base__: crate::IUnknown_Vtbl { QueryInterface: Self::StrongQueryInterface, AddRef: Self::StrongAddRef, Release: Self::StrongRelease }, + base__: crate::IUnknown_Vtbl { + QueryInterface: Self::StrongQueryInterface, + AddRef: Self::StrongAddRef, + Release: Self::StrongRelease, + }, GetWeakReference: Self::StrongDowngrade, }; const WEAK_VTABLE: IWeakReference_Vtbl = IWeakReference_Vtbl { - base__: crate::IUnknown_Vtbl { QueryInterface: Self::WeakQueryInterface, AddRef: Self::WeakAddRef, Release: Self::WeakRelease }, + base__: crate::IUnknown_Vtbl { + QueryInterface: Self::WeakQueryInterface, + AddRef: Self::WeakAddRef, + Release: Self::WeakRelease, + }, Resolve: Self::WeakUpgrade, }; @@ -127,11 +154,23 @@ impl TearOff { transmute(value << 1) } - unsafe fn query_interface(&self, iid: *const crate::GUID, interface: *mut *mut c_void) -> crate::HRESULT { - ((*(*(self.object as *mut *mut crate::IUnknown_Vtbl))).QueryInterface)(self.object, iid, interface) + unsafe fn query_interface( + &self, + iid: *const crate::GUID, + interface: *mut *mut c_void, + ) -> crate::HRESULT { + ((*(*(self.object as *mut *mut crate::IUnknown_Vtbl))).QueryInterface)( + self.object, + iid, + interface, + ) } - unsafe extern "system" fn StrongQueryInterface(ptr: *mut c_void, iid: *const crate::GUID, interface: *mut *mut c_void) -> crate::HRESULT { + unsafe extern "system" fn StrongQueryInterface( + ptr: *mut c_void, + iid: *const crate::GUID, + interface: *mut *mut c_void, + ) -> crate::HRESULT { let this = Self::from_strong_ptr(ptr); if iid.is_null() || interface.is_null() { @@ -151,7 +190,11 @@ impl TearOff { this.query_interface(iid, interface) } - unsafe extern "system" fn WeakQueryInterface(ptr: *mut c_void, iid: *const crate::GUID, interface: *mut *mut c_void) -> crate::HRESULT { + unsafe extern "system" fn WeakQueryInterface( + ptr: *mut c_void, + iid: *const crate::GUID, + interface: *mut *mut c_void, + ) -> crate::HRESULT { let this = Self::from_weak_ptr(ptr); if iid.is_null() || interface.is_null() { @@ -162,7 +205,14 @@ impl TearOff { // tear-off, it represents a distinct COM identity and thus does not share or delegate to // the object. - *interface = if *iid == IWeakReference::IID || *iid == crate::IUnknown::IID || *iid == IAgileObject::IID { ptr } else { null_mut() }; + *interface = if *iid == IWeakReference::IID + || *iid == crate::IUnknown::IID + || *iid == IAgileObject::IID + { + ptr + } else { + null_mut() + }; // TODO: implement IMarshal @@ -211,7 +261,10 @@ impl TearOff { remaining } - unsafe extern "system" fn StrongDowngrade(ptr: *mut c_void, interface: *mut *mut c_void) -> crate::HRESULT { + unsafe extern "system" fn StrongDowngrade( + ptr: *mut c_void, + interface: *mut *mut c_void, + ) -> crate::HRESULT { let this = Self::from_strong_ptr(ptr); // The strong vtable hands out a reference to the weak vtable. This is always safe and @@ -222,7 +275,11 @@ impl TearOff { crate::HRESULT(0) } - unsafe extern "system" fn WeakUpgrade(ptr: *mut c_void, iid: *const crate::GUID, interface: *mut *mut c_void) -> crate::HRESULT { + unsafe extern "system" fn WeakUpgrade( + ptr: *mut c_void, + iid: *const crate::GUID, + interface: *mut *mut c_void, + ) -> crate::HRESULT { let this = Self::from_weak_ptr(ptr); this.strong_count diff --git a/crates/libs/core/src/inspectable.rs b/crates/libs/core/src/inspectable.rs index 44cefe4beb..fba5524524 100644 --- a/crates/libs/core/src/inspectable.rs +++ b/crates/libs/core/src/inspectable.rs @@ -37,8 +37,13 @@ impl IInspectable { #[repr(C)] pub struct IInspectable_Vtbl { pub base: IUnknown_Vtbl, - pub GetIids: unsafe extern "system" fn(this: *mut c_void, count: *mut u32, values: *mut *mut GUID) -> HRESULT, - pub GetRuntimeClassName: unsafe extern "system" fn(this: *mut c_void, value: *mut *mut c_void) -> HRESULT, + pub GetIids: unsafe extern "system" fn( + this: *mut c_void, + count: *mut u32, + values: *mut *mut GUID, + ) -> HRESULT, + pub GetRuntimeClassName: + unsafe extern "system" fn(this: *mut c_void, value: *mut *mut c_void) -> HRESULT, pub GetTrustLevel: unsafe extern "system" fn(this: *mut c_void, value: *mut i32) -> HRESULT, } @@ -95,7 +100,10 @@ impl core::fmt::Debug for IInspectable { // 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 = ::cast::(self).and_then(|s| s.ToString()).or_else(|_| self.GetRuntimeClassName()).unwrap_or_default(); + let name = ::cast::(self) + .and_then(|s| s.ToString()) + .or_else(|_| self.GetRuntimeClassName()) + .unwrap_or_default(); write!(f, "\"{}\"", name) } } diff --git a/crates/libs/core/src/interface.rs b/crates/libs/core/src/interface.rs index c10991b9a7..7b2a231e42 100644 --- a/crates/libs/core/src/interface.rs +++ b/crates/libs/core/src/interface.rs @@ -1,7 +1,8 @@ use super::*; +use core::any::Any; use core::ffi::c_void; use core::marker::PhantomData; -use core::mem::{forget, transmute_copy}; +use core::mem::{forget, transmute_copy, MaybeUninit}; use core::ptr::NonNull; /// Provides low-level access to an interface vtable. @@ -97,7 +98,7 @@ pub unsafe trait Interface: Sized + Clone { // // This guards against implementations of COM interfaces which may store non-null values // in 'result' but still return E_NOINTERFACE. - let mut result = core::mem::MaybeUninit::>::zeroed(); + let mut result = MaybeUninit::>::zeroed(); self.query(&T::IID, result.as_mut_ptr() as _).ok()?; // If we get here, then query() has succeeded, but we still need to double-check @@ -110,9 +111,131 @@ pub unsafe trait Interface: Sized + Clone { } } + /// This casts the given COM interface to [`&dyn Any`]. + /// + /// Applications should generally _not_ call this method directly. Instead, use the + /// [`Interface::cast_object_ref`] or [`Interface::cast_object`] methods. + /// + /// `T` must be a type that has been annotated with `#[implement]`; this is checked at + /// compile-time by the generic constraints of this method. However, note that the + /// returned `&dyn Any` refers to the _outer_ implementation object that was generated by + /// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type. + /// + /// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust + /// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`. + /// + /// # Safety + /// + /// **IMPORTANT!!** This uses a non-standard protocol for QueryInterface! The `DYNAMIC_CAST_IID` + /// IID identifies this protocol, but there is no `IDynamicCast` interface. Instead, objects + /// that recognize `DYNAMIC_CAST_IID` simply store their `&dyn Any` directly at the interface + /// pointer that was passed to `QueryInterface. This means that the returned value has a + /// size that is twice as large (`size_of::<&dyn Any>() == 2 * size_of::<*const c_void>()`). + /// + /// This means that callers that use this protocol cannot simply pass `&mut ptr` for + /// an ordinary single-pointer-sized pointer. Only this method understands this protocol. + /// + /// Another part of this protocol is that the implementation of `QueryInterface` _does not_ + /// AddRef the object. The caller must guarantee the liveness of the COM object. In Rust, + /// this means tying the lifetime of the IUnknown* that we used for the QueryInterface + /// call to the lifetime of the returned `&dyn Any` value. + /// + /// This method preserves type safety and relies on these invariants: + /// + /// * All `QueryInterface` implementations that recognize `DYNAMIC_CAST_IID` are generated by + /// the `#[implement]` macro and respect the rules described here. + #[inline(always)] + fn cast_to_any(&self) -> Result<&dyn Any> + where + T: ComObjectInner, + T::Outer: Any + 'static + IUnknownImpl, + { + unsafe { + let mut any_ref_arg: MaybeUninit<&dyn Any> = MaybeUninit::zeroed(); + self.query( + &DYNAMIC_CAST_IID, + any_ref_arg.as_mut_ptr() as *mut *mut c_void, + ) + .ok()?; + Ok(any_ref_arg.assume_init()) + } + } + + /// Returns `true` if the given COM interface refers to an implementation of `T`. + /// + /// `T` must be a type that has been annotated with `#[implement]`; this is checked at + /// compile-time by the generic constraints of this method. + /// + /// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust + /// object that contains non-static lifetimes, then this function will return `false`. + #[inline(always)] + fn is_object(&self) -> bool + where + T: ComObjectInner, + T::Outer: Any + 'static + IUnknownImpl, + { + if let Ok(any) = self.cast_to_any::() { + any.is::() + } else { + false + } + } + + /// This casts the given COM interface to [`&dyn Any`]. It returns a reference to the "outer" + /// object, e.g. `&MyApp_Impl`, not the inner `&MyApp` object. + /// + /// `T` must be a type that has been annotated with `#[implement]`; this is checked at + /// compile-time by the generic constraints of this method. However, note that the + /// returned `&dyn Any` refers to the _outer_ implementation object that was generated by + /// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type. + /// + /// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust + /// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`. + /// + /// The returned value is borrowed. If you need an owned (counted) reference, then use + /// [`Interface::cast_object`]. + #[inline(always)] + fn cast_object_ref(&self) -> Result<&T::Outer> + where + T: ComObjectInner, + T::Outer: Any + 'static + IUnknownImpl, + { + let any: &dyn Any = self.cast_to_any::()?; + if let Some(outer) = any.downcast_ref::() { + Ok(outer) + } else { + Err(imp::E_NOINTERFACE.into()) + } + } + + /// This casts the given COM interface to [`&dyn Any`]. It returns a reference to the "outer" + /// object, e.g. `MyApp_Impl`, not the inner `MyApp` object. + /// + /// `T` must be a type that has been annotated with `#[implement]`; this is checked at + /// compile-time by the generic constraints of this method. However, note that the + /// returned `&dyn Any` refers to the _outer_ implementation object that was generated by + /// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type. + /// + /// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust + /// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`. + /// + /// The returned value is an owned (counted) reference; this function calls `AddRef` on the + /// underlying COM object. If you do not need an owned reference, then you can use the + /// [`Interface::cast_object_ref`] method instead, and avoid the cost of `AddRef` / `Release`. + #[inline(always)] + fn cast_object(&self) -> Result> + where + T: ComObjectInner, + T::Outer: Any + 'static + IUnknownImpl, + { + let object_ref = self.cast_object_ref::()?; + Ok(object_ref.to_object()) + } + /// Attempts to create a [`Weak`] reference to this object. fn downgrade(&self) -> Result> { - self.cast::().and_then(|source| Weak::downgrade(&source)) + self.cast::() + .and_then(|source| Weak::downgrade(&source)) } /// Call `QueryInterface` on this interface @@ -210,3 +333,9 @@ impl<'a, I: Interface> core::ops::Deref for InterfaceRef<'a, I> { unsafe { core::mem::transmute(self) } } } + +/// This IID identifies a special protocol, used by [`Interface::cast_to_any`]. This is _not_ +/// an ordinary COM interface; it uses special lifetime rules and a larger interface pointer. +/// See the comments on [`Interface::cast_to_any`]. +#[doc(hidden)] +pub const DYNAMIC_CAST_IID: GUID = GUID::from_u128(0xae49d5cb_143f_431c_874c_2729336e4eca); diff --git a/crates/libs/core/src/lib.rs b/crates/libs/core/src/lib.rs index 756c3637a1..25708a4c6d 100644 --- a/crates/libs/core/src/lib.rs +++ b/crates/libs/core/src/lib.rs @@ -4,7 +4,10 @@ Learn more about Rust for Windows here: ParamValue { if U::QUERY { - self.cast().map_or(ParamValue::Borrowed(zeroed()), |ok| ParamValue::Owned(ok)) + self.cast() + .map_or(ParamValue::Borrowed(zeroed()), |ok| ParamValue::Owned(ok)) } else { ParamValue::Borrowed(transmute_copy(self)) } diff --git a/crates/libs/core/src/scoped_interface.rs b/crates/libs/core/src/scoped_interface.rs index 96ae377fad..09f9298978 100644 --- a/crates/libs/core/src/scoped_interface.rs +++ b/crates/libs/core/src/scoped_interface.rs @@ -17,7 +17,10 @@ pub struct ScopedInterface<'a, T: Interface> { impl<'a, T: Interface> ScopedInterface<'a, T> { pub fn new(interface: T) -> Self { - Self { interface, lifetime: PhantomData } + Self { + interface, + lifetime: PhantomData, + } } } diff --git a/crates/libs/core/src/strings/bstr.rs b/crates/libs/core/src/strings/bstr.rs index 3b44ffe7af..750ff32075 100644 --- a/crates/libs/core/src/strings/bstr.rs +++ b/crates/libs/core/src/strings/bstr.rs @@ -48,7 +48,12 @@ impl BSTR { return Ok(Self::new()); } - let result = unsafe { Self(imp::SysAllocStringLen(value.as_ptr(), value.len().try_into()?)) }; + let result = unsafe { + Self(imp::SysAllocStringLen( + value.as_ptr(), + value.len().try_into()?, + )) + }; if result.is_empty() { Err(imp::E_OUTOFMEMORY.into()) @@ -119,7 +124,11 @@ impl Default for BSTR { impl core::fmt::Display for BSTR { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - core::write!(f, "{}", Decode(|| core::char::decode_utf16(self.as_wide().iter().cloned()))) + core::write!( + f, + "{}", + Decode(|| core::char::decode_utf16(self.as_wide().iter().cloned())) + ) } } @@ -151,7 +160,10 @@ impl PartialEq for String { impl + ?Sized> PartialEq for BSTR { fn eq(&self, other: &T) -> bool { - self.as_wide().iter().copied().eq(other.as_ref().encode_utf16()) + self.as_wide() + .iter() + .copied() + .eq(other.as_ref().encode_utf16()) } } diff --git a/crates/libs/core/src/strings/hstring.rs b/crates/libs/core/src/strings/hstring.rs index 369754987d..daa647011f 100644 --- a/crates/libs/core/src/strings/hstring.rs +++ b/crates/libs/core/src/strings/hstring.rs @@ -127,7 +127,11 @@ unsafe impl Sync for HSTRING {} impl core::fmt::Display for HSTRING { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{}", Decode(|| core::char::decode_utf16(self.as_wide().iter().cloned()))) + write!( + f, + "{}", + Decode(|| core::char::decode_utf16(self.as_wide().iter().cloned())) + ) } } @@ -165,7 +169,13 @@ impl From<&std::path::Path> for HSTRING { #[cfg(all(feature = "std", windows))] impl From<&std::ffi::OsStr> for HSTRING { fn from(value: &std::ffi::OsStr) -> Self { - unsafe { Self::from_wide_iter(std::os::windows::ffi::OsStrExt::encode_wide(value), value.len()).unwrap() } + unsafe { + Self::from_wide_iter( + std::os::windows::ffi::OsStrExt::encode_wide(value), + value.len(), + ) + .unwrap() + } } } @@ -305,7 +315,10 @@ impl PartialEq<&std::ffi::OsString> for HSTRING { #[cfg(all(feature = "std", windows))] impl PartialEq for HSTRING { fn eq(&self, other: &std::ffi::OsStr) -> bool { - self.as_wide().iter().copied().eq(std::os::windows::ffi::OsStrExt::encode_wide(other)) + self.as_wide() + .iter() + .copied() + .eq(std::os::windows::ffi::OsStrExt::encode_wide(other)) } } diff --git a/crates/libs/core/src/strings/literals.rs b/crates/libs/core/src/strings/literals.rs index e9d14f3252..493ca14bd6 100644 --- a/crates/libs/core/src/strings/literals.rs +++ b/crates/libs/core/src/strings/literals.rs @@ -47,9 +47,17 @@ macro_rules! h { unsafe { ::std::mem::transmute(::std::ptr::null::()) } } else { const OUTPUT: $crate::PCWSTR = $crate::w!($s); - const HEADER: $crate::HSTRING_HEADER = $crate::HSTRING_HEADER { flags: 0x11, len: (OUTPUT_LEN - 1) as u32, padding1: 0, padding2: 0, ptr: OUTPUT.as_ptr() }; + const HEADER: $crate::HSTRING_HEADER = $crate::HSTRING_HEADER { + flags: 0x11, + len: (OUTPUT_LEN - 1) as u32, + padding1: 0, + padding2: 0, + ptr: OUTPUT.as_ptr(), + }; // SAFETY: an `HSTRING` is exactly equivalent to a pointer to an `HSTRING_HEADER` - unsafe { ::std::mem::transmute::<&$crate::HSTRING_HEADER, $crate::HSTRING>(&HEADER) } + unsafe { + ::std::mem::transmute::<&$crate::HSTRING_HEADER, $crate::HSTRING>(&HEADER) + } } }; #[allow(clippy::borrow_interior_mutable_const)] @@ -112,7 +120,8 @@ pub const fn decode_utf8_char(bytes: &[u8], mut pos: usize) -> Option<(u32, usiz if (ch2 & 0xc0) != 0x80 || (ch3 & 0xc0) != 0x80 || (ch4 & 0xc0) != 0x80 { return None; } - let result = ((ch & 0x07) << 18) | ((ch2 & 0x3f) << 12) | ((ch3 & 0x3f) << 6) | (ch4 & 0x3f); + let result = + ((ch & 0x07) << 18) | ((ch2 & 0x3f) << 12) | ((ch3 & 0x3f) << 6) | (ch4 & 0x3f); if result <= 0xffff || 0x10ffff < result { return None; } diff --git a/crates/libs/core/src/strings/mod.rs b/crates/libs/core/src/strings/mod.rs index 320ce17436..3033118c97 100644 --- a/crates/libs/core/src/strings/mod.rs +++ b/crates/libs/core/src/strings/mod.rs @@ -41,7 +41,9 @@ where } /// Mirror of `std::char::decode_utf16` for utf-8. -fn decode_utf8(mut buffer: &[u8]) -> impl Iterator> + '_ { +fn decode_utf8( + mut buffer: &[u8], +) -> impl Iterator> + '_ { let mut current = "".chars(); let mut previous_error = None; core::iter::from_fn(move || { diff --git a/crates/libs/core/src/unknown.rs b/crates/libs/core/src/unknown.rs index 1fe088636f..1f16b35a0d 100644 --- a/crates/libs/core/src/unknown.rs +++ b/crates/libs/core/src/unknown.rs @@ -13,7 +13,11 @@ pub struct IUnknown(NonNull); #[repr(C)] #[allow(non_camel_case_types)] pub struct IUnknown_Vtbl { - pub QueryInterface: unsafe extern "system" fn(this: *mut c_void, iid: *const GUID, interface: *mut *mut c_void) -> HRESULT, + pub QueryInterface: unsafe extern "system" fn( + this: *mut c_void, + iid: *const GUID, + interface: *mut *mut c_void, + ) -> HRESULT, pub AddRef: unsafe extern "system" fn(this: *mut c_void) -> u32, pub Release: unsafe extern "system" fn(this: *mut c_void) -> u32, } @@ -55,7 +59,7 @@ impl Eq for IUnknown {} impl core::fmt::Debug for IUnknown { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_tuple("IUnknown").field(&self.0).finish() + f.debug_tuple("IUnknown").field(&self.as_raw()).finish() } } @@ -135,22 +139,49 @@ pub trait IUnknownImpl { { >::as_interface_ref(self).to_owned() } + + /// Creates a new owned reference to this object. + /// + /// # Safety + /// + /// This function can only be safely called by `_Impl` objects that are embedded in a + /// `ComObject`. Since we only allow safe Rust code to access these objects using a `ComObject` + /// or a `&_Impl` that points within a `ComObject`, this is safe. + fn to_object(&self) -> ComObject + where + Self::Impl: ComObjectInner; + + /// The distance from the start of `_Impl` to the `this` field within it, measured in + /// pointer-sized elements. The `this` field contains the `MyApp` instance. + const INNER_OFFSET_IN_POINTERS: usize; } impl IUnknown_Vtbl { pub const fn new() -> Self { - unsafe extern "system" fn QueryInterface(this: *mut c_void, iid: *const GUID, interface: *mut *mut c_void) -> HRESULT { + unsafe extern "system" fn QueryInterface( + this: *mut c_void, + iid: *const GUID, + interface: *mut *mut c_void, + ) -> HRESULT { let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T; (*this).QueryInterface(iid, interface) } - unsafe extern "system" fn AddRef(this: *mut c_void) -> u32 { + unsafe extern "system" fn AddRef( + this: *mut c_void, + ) -> u32 { let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T; (*this).AddRef() } - unsafe extern "system" fn Release(this: *mut c_void) -> u32 { + unsafe extern "system" fn Release( + this: *mut c_void, + ) -> u32 { let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T; T::Release(this) } - Self { QueryInterface: QueryInterface::, AddRef: AddRef::, Release: Release:: } + Self { + QueryInterface: QueryInterface::, + AddRef: AddRef::, + Release: Release::, + } } } diff --git a/crates/libs/core/src/variant.rs b/crates/libs/core/src/variant.rs index a55dfe0669..ca85aa0c10 100644 --- a/crates/libs/core/src/variant.rs +++ b/crates/libs/core/src/variant.rs @@ -214,7 +214,15 @@ impl From for VARIANT { fn from(value: IUnknown) -> Self { Self(imp::VARIANT { Anonymous: imp::VARIANT_0 { - Anonymous: imp::VARIANT_0_0 { vt: imp::VT_UNKNOWN, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { punkVal: value.into_raw() } }, + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_UNKNOWN, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { + punkVal: value.into_raw(), + }, + }, }, }) } @@ -224,7 +232,15 @@ impl From for PROPVARIANT { fn from(value: IUnknown) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_UNKNOWN, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { punkVal: value.into_raw() } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_UNKNOWN, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { + punkVal: value.into_raw(), + }, + }, }, }) } @@ -234,7 +250,9 @@ impl TryFrom<&VARIANT> for IUnknown { type Error = Error; fn try_from(from: &VARIANT) -> Result { unsafe { - if from.0.Anonymous.Anonymous.vt == imp::VT_UNKNOWN && !from.0.Anonymous.Anonymous.Anonymous.punkVal.is_null() { + if from.0.Anonymous.Anonymous.vt == imp::VT_UNKNOWN + && !from.0.Anonymous.Anonymous.Anonymous.punkVal.is_null() + { let unknown: &IUnknown = transmute(&from.0.Anonymous.Anonymous.Anonymous.punkVal); Ok(unknown.clone()) } else { @@ -248,7 +266,9 @@ impl TryFrom<&PROPVARIANT> for IUnknown { type Error = Error; fn try_from(from: &PROPVARIANT) -> Result { unsafe { - if from.0.Anonymous.Anonymous.vt == imp::VT_UNKNOWN && !from.0.Anonymous.Anonymous.Anonymous.punkVal.is_null() { + if from.0.Anonymous.Anonymous.vt == imp::VT_UNKNOWN + && !from.0.Anonymous.Anonymous.Anonymous.punkVal.is_null() + { let unknown: &IUnknown = transmute(&from.0.Anonymous.Anonymous.Anonymous.punkVal); Ok(unknown.clone()) } else { @@ -264,7 +284,15 @@ impl From for VARIANT { fn from(value: BSTR) -> Self { Self(imp::VARIANT { Anonymous: imp::VARIANT_0 { - Anonymous: imp::VARIANT_0_0 { vt: imp::VT_BSTR, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { bstrVal: value.into_raw() } }, + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_BSTR, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { + bstrVal: value.into_raw(), + }, + }, }, }) } @@ -274,7 +302,15 @@ impl From for PROPVARIANT { fn from(value: BSTR) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_BSTR, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { bstrVal: value.into_raw() } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_BSTR, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { + bstrVal: value.into_raw(), + }, + }, }, }) } @@ -304,7 +340,8 @@ impl TryFrom<&PROPVARIANT> for BSTR { type Error = Error; fn try_from(from: &PROPVARIANT) -> Result { let mut value = Self::new(); - HRESULT(unsafe { imp::PropVariantToBSTR(&from.0, &mut value as *mut _ as *mut _) }).map(|| value) + HRESULT(unsafe { imp::PropVariantToBSTR(&from.0, &mut value as *mut _ as *mut _) }) + .map(|| value) } } @@ -314,7 +351,15 @@ impl From for VARIANT { fn from(value: bool) -> Self { Self(imp::VARIANT { Anonymous: imp::VARIANT_0 { - Anonymous: imp::VARIANT_0_0 { vt: imp::VT_BOOL, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { boolVal: if value { -1 } else { 0 } } }, + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_BOOL, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { + boolVal: if value { -1 } else { 0 }, + }, + }, }, }) } @@ -324,7 +369,15 @@ impl From for PROPVARIANT { fn from(value: bool) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_BOOL, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { boolVal: if value { -1 } else { 0 } } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_BOOL, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { + boolVal: if value { -1 } else { 0 }, + }, + }, }, }) } @@ -351,7 +404,15 @@ impl TryFrom<&PROPVARIANT> for bool { impl From for VARIANT { fn from(value: u8) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_UI1, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { bVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_UI1, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { bVal: value }, + }, + }, }) } } @@ -360,7 +421,13 @@ impl From for PROPVARIANT { fn from(value: u8) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_UI1, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { bVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_UI1, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { bVal: value }, + }, }, }) } @@ -371,7 +438,15 @@ impl From for PROPVARIANT { impl From for VARIANT { fn from(value: i8) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_I1, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { cVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_I1, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { cVal: value }, + }, + }, }) } } @@ -380,7 +455,13 @@ impl From for PROPVARIANT { fn from(value: i8) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_I1, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { cVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_I1, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { cVal: value }, + }, }, }) } @@ -391,7 +472,15 @@ impl From for PROPVARIANT { impl From for VARIANT { fn from(value: u16) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_UI2, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { uiVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_UI2, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { uiVal: value }, + }, + }, }) } } @@ -400,7 +489,13 @@ impl From for PROPVARIANT { fn from(value: u16) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_UI2, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { uiVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_UI2, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { uiVal: value }, + }, }, }) } @@ -427,7 +522,15 @@ impl TryFrom<&PROPVARIANT> for u16 { impl From for VARIANT { fn from(value: i16) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_I2, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { iVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_I2, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { iVal: value }, + }, + }, }) } } @@ -436,7 +539,13 @@ impl From for PROPVARIANT { fn from(value: i16) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_I2, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { iVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_I2, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { iVal: value }, + }, }, }) } @@ -463,7 +572,15 @@ impl TryFrom<&PROPVARIANT> for i16 { impl From for VARIANT { fn from(value: u32) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_UI4, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { ulVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_UI4, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { ulVal: value }, + }, + }, }) } } @@ -472,7 +589,13 @@ impl From for PROPVARIANT { fn from(value: u32) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_UI4, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { ulVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_UI4, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { ulVal: value }, + }, }, }) } @@ -499,7 +622,15 @@ impl TryFrom<&PROPVARIANT> for u32 { impl From for VARIANT { fn from(value: i32) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_I4, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { lVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_I4, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { lVal: value }, + }, + }, }) } } @@ -508,7 +639,13 @@ impl From for PROPVARIANT { fn from(value: i32) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_I4, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { lVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_I4, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { lVal: value }, + }, }, }) } @@ -535,7 +672,15 @@ impl TryFrom<&PROPVARIANT> for i32 { impl From for VARIANT { fn from(value: u64) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_UI8, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { ullVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_UI8, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { ullVal: value }, + }, + }, }) } } @@ -544,7 +689,13 @@ impl From for PROPVARIANT { fn from(value: u64) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_UI8, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { uhVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_UI8, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { uhVal: value }, + }, }, }) } @@ -571,7 +722,15 @@ impl TryFrom<&PROPVARIANT> for u64 { impl From for VARIANT { fn from(value: i64) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_I8, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { llVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_I8, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { llVal: value }, + }, + }, }) } } @@ -580,7 +739,13 @@ impl From for PROPVARIANT { fn from(value: i64) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_I8, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { hVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_I8, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { hVal: value }, + }, }, }) } @@ -607,7 +772,15 @@ impl TryFrom<&PROPVARIANT> for i64 { impl From for VARIANT { fn from(value: f32) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_R4, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { fltVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_R4, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { fltVal: value }, + }, + }, }) } } @@ -616,7 +789,13 @@ impl From for PROPVARIANT { fn from(value: f32) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_R4, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { fltVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_R4, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { fltVal: value }, + }, }, }) } @@ -627,7 +806,15 @@ impl From for PROPVARIANT { impl From for VARIANT { fn from(value: f64) -> Self { Self(imp::VARIANT { - Anonymous: imp::VARIANT_0 { Anonymous: imp::VARIANT_0_0 { vt: imp::VT_R8, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::VARIANT_0_0_0 { dblVal: value } } }, + Anonymous: imp::VARIANT_0 { + Anonymous: imp::VARIANT_0_0 { + vt: imp::VT_R8, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::VARIANT_0_0_0 { dblVal: value }, + }, + }, }) } } @@ -636,7 +823,13 @@ impl From for PROPVARIANT { fn from(value: f64) -> Self { Self(imp::PROPVARIANT { Anonymous: imp::PROPVARIANT_0 { - Anonymous: imp::PROPVARIANT_0_0 { vt: imp::VT_R8, wReserved1: 0, wReserved2: 0, wReserved3: 0, Anonymous: imp::PROPVARIANT_0_0_0 { dblVal: value } }, + Anonymous: imp::PROPVARIANT_0_0 { + vt: imp::VT_R8, + wReserved1: 0, + wReserved2: 0, + wReserved3: 0, + Anonymous: imp::PROPVARIANT_0_0_0 { dblVal: value }, + }, }, }) } diff --git a/crates/libs/core/src/weak.rs b/crates/libs/core/src/weak.rs index cb052f26cf..677543d6e7 100644 --- a/crates/libs/core/src/weak.rs +++ b/crates/libs/core/src/weak.rs @@ -13,7 +13,9 @@ impl Weak { /// Attempts to upgrade the weak reference to a strong reference. pub fn upgrade(&self) -> Option { - self.0.as_ref().and_then(|inner| unsafe { inner.Resolve().ok() }) + self.0 + .as_ref() + .and_then(|inner| unsafe { inner.Resolve().ok() }) } pub(crate) fn downgrade(source: &imp::IWeakReferenceSource) -> Result { diff --git a/crates/libs/cppwinrt/Cargo.toml b/crates/libs/cppwinrt/Cargo.toml new file mode 100644 index 0000000000..3d705640b9 --- /dev/null +++ b/crates/libs/cppwinrt/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "cppwinrt" +version = "0.1.0" +authors = ["Microsoft"] +edition = "2021" +rust-version = "1.60" +license = "MIT OR Apache-2.0" +description = "C++/WinRT" +repository = "https://github.com/microsoft/windows-rs" +readme = "readme.md" +categories = ["os::windows-apis"] + +[lints] +workspace = true + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff --git a/crates/libs/cppwinrt/cppwinrt.exe b/crates/libs/cppwinrt/cppwinrt.exe new file mode 100644 index 0000000000..a53d530a14 Binary files /dev/null and b/crates/libs/cppwinrt/cppwinrt.exe differ diff --git a/crates/libs/cppwinrt/license-apache-2.0 b/crates/libs/cppwinrt/license-apache-2.0 new file mode 100644 index 0000000000..b5ed4ecec2 --- /dev/null +++ b/crates/libs/cppwinrt/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/crates/libs/cppwinrt/license-mit b/crates/libs/cppwinrt/license-mit new file mode 100644 index 0000000000..9e841e7a26 --- /dev/null +++ b/crates/libs/cppwinrt/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/crates/libs/cppwinrt/readme.md b/crates/libs/cppwinrt/readme.md new file mode 100644 index 0000000000..d0886d9241 --- /dev/null +++ b/crates/libs/cppwinrt/readme.md @@ -0,0 +1,31 @@ +## C++/WinRT + +The [cppwinrt](https://crates.io/crates/cppwinrt) crate bundles the C++/WinRT compiler for use in Rust. + +* [Getting started](https://kennykerr.ca/rust-getting-started/) +* [Samples](https://github.com/microsoft/windows-rs/tree/0.56.0/crates/samples) +* [Releases](https://github.com/microsoft/windows-rs/releases) + +Start by adding the following to your Cargo.toml file: + +```toml +[dependencies.cppwinrt] +version = "0.1" +``` + +Use `cppwinrt` function as needed: + +```rust +fn main() { + match cppwinrt::cppwinrt(["-help"]) { + Ok(output) => println!("{output}"), + Err(error) => println!("{error}"), + }; +} +``` + +Source: + +* +* +* Version 2.0.240405.15 diff --git a/crates/libs/cppwinrt/src/lib.rs b/crates/libs/cppwinrt/src/lib.rs new file mode 100644 index 0000000000..1819774a38 --- /dev/null +++ b/crates/libs/cppwinrt/src/lib.rs @@ -0,0 +1,43 @@ +/*! +Learn more about Rust for Windows here: +*/ + +const VERSION: &str = "2.0.240405.15"; + +/// Calls the C++/WinRT compiler with the given arguments. +/// +/// Use `cppwinrt["-help"]` for available options. +pub fn cppwinrt(args: I) -> Result +where + I: IntoIterator, + S: AsRef, +{ + let mut path = std::env::temp_dir(); + path.push(format!("cppwinrt-{VERSION}.exe")); + + std::fs::write(&path, std::include_bytes!("../cppwinrt.exe")).unwrap(); + let mut command = std::process::Command::new(&path); + command.args(args); + let output = command.output().expect("failed to run cppwinrt"); + _ = std::fs::remove_file(path); + + if output.status.success() { + Ok(String::from_utf8_lossy(&output.stdout).to_string()) + } else { + Err(String::from_utf8_lossy(&output.stderr).to_string()) + } +} + +#[cfg(test)] +mod tests { + use crate::*; + + #[test] + fn test() { + let ok = cppwinrt(["-help"]).unwrap(); + assert!(ok.contains(VERSION), "unexpected version"); + + let err = cppwinrt(["-invalid"]).unwrap_err(); + assert!(err.contains("'-invalid' is not supported")); + } +} diff --git a/crates/libs/implement/src/lib.rs b/crates/libs/implement/src/lib.rs index 06c6536ab4..4fa01941a4 100644 --- a/crates/libs/implement/src/lib.rs +++ b/crates/libs/implement/src/lib.rs @@ -33,7 +33,10 @@ use quote::{quote, ToTokens}; /// } /// ``` #[proc_macro_attribute] -pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro::TokenStream) -> proc_macro::TokenStream { +pub fn implement( + attributes: proc_macro::TokenStream, + original_type: proc_macro::TokenStream, +) -> proc_macro::TokenStream { let attributes = syn::parse_macro_input!(attributes as ImplementAttributes); let interfaces_len = proc_macro2::Literal::usize_unsuffixed(attributes.implement.len()); @@ -46,10 +49,10 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: let original_type2 = original_type.clone(); let original_type2 = syn::parse_macro_input!(original_type2 as syn::ItemStruct); let vis = &original_type2.vis; - let original_ident = original_type2.ident; + let original_ident = &original_type2.ident; let mut constraints = quote! {}; - if let Some(where_clause) = original_type2.generics.where_clause { + if let Some(where_clause) = &original_type2.generics.where_clause { where_clause.predicates.to_tokens(&mut constraints); } @@ -62,30 +65,65 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: }; let impl_ident = quote::format_ident!("{}_Impl", original_ident); - let vtbl_idents = attributes.implement.iter().map(|implement| implement.to_vtbl_ident()); + let vtbl_idents = attributes + .implement + .iter() + .map(|implement| implement.to_vtbl_ident()); let vtbl_idents2 = vtbl_idents.clone(); - let vtable_news = attributes.implement.iter().enumerate().map(|(enumerate, implement)| { - let vtbl_ident = implement.to_vtbl_ident(); - let offset = proc_macro2::Literal::isize_unsuffixed(-1 - enumerate as isize); - quote! { #vtbl_ident::new::() } - }); - - let offset = attributes.implement.iter().enumerate().map(|(offset, _)| proc_macro2::Literal::usize_unsuffixed(offset)); + let vtable_news = attributes + .implement + .iter() + .enumerate() + .map(|(enumerate, implement)| { + let vtbl_ident = implement.to_vtbl_ident(); + let offset = proc_macro2::Literal::isize_unsuffixed(-1 - enumerate as isize); + quote! { #vtbl_ident::new::() } + }); + + let offset = attributes + .implement + .iter() + .enumerate() + .map(|(offset, _)| proc_macro2::Literal::usize_unsuffixed(offset)); + + let queries = attributes + .implement + .iter() + .enumerate() + .map(|(count, implement)| { + let vtbl_ident = implement.to_vtbl_ident(); + let offset = proc_macro2::Literal::usize_unsuffixed(count); + quote! { + else if #vtbl_ident::matches(iid) { + &self.vtables.#offset as *const _ as *mut _ + } + } + }); - let queries = attributes.implement.iter().enumerate().map(|(count, implement)| { - let vtbl_ident = implement.to_vtbl_ident(); - let offset = proc_macro2::Literal::usize_unsuffixed(count); + // Dynamic casting requires that the object not contain non-static lifetimes. + let enable_dyn_casting = original_type2.generics.lifetimes().count() == 0; + let dynamic_cast_query = if enable_dyn_casting { quote! { - else if #vtbl_ident::matches(iid) { - &self.vtables.#offset as *const _ as *mut _ + else if *iid == ::windows_core::DYNAMIC_CAST_IID { + // DYNAMIC_CAST_IID is special. We _do not_ increase the reference count for this pseudo-interface. + // Also, instead of returning an interface pointer, we simply write the `&dyn Any` directly to the + // 'interface' pointer. Since the size of `&dyn Any` is 2 pointers, not one, the caller must be + // prepared for this. This is not a normal QueryInterface call. + // + // See the `Interface::cast_to_any` method, which is the only caller that should use DYNAMIC_CAST_ID. + (interface as *mut *const dyn core::any::Any).write(self as &dyn ::core::any::Any as *const dyn ::core::any::Any); + return ::windows_core::HRESULT(0); } } - }); + } else { + quote!() + }; // The distance from the beginning of the generated type to the 'this' field, in units of pointers (not bytes). let offset_of_this_in_pointers = 1 + attributes.implement.len(); - let offset_of_this_in_pointers_token = proc_macro2::Literal::usize_unsuffixed(offset_of_this_in_pointers); + let offset_of_this_in_pointers_token = + proc_macro2::Literal::usize_unsuffixed(offset_of_this_in_pointers); let trust_level = proc_macro2::Literal::usize_unsuffixed(attributes.trust_level); @@ -201,7 +239,10 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: || iid == &<::windows_core::IInspectable as ::windows_core::Interface>::IID || iid == &<::windows_core::imp::IAgileObject as ::windows_core::Interface>::IID { &self.identity as *const _ as *mut _ - } #(#queries)* else { + } + #(#queries)* + #dynamic_cast_query + else { ::core::ptr::null_mut() }; @@ -230,7 +271,7 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: unsafe fn Release(self_: *mut Self) -> u32 { let remaining = (*self_).count.release(); if remaining == 0 { - _ = ::windows_core::imp::Box::from_raw(self_ as *const Self as *mut Self); + _ = ::windows_core::imp::Box::from_raw(self_); } remaining } @@ -247,6 +288,17 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: &*((inner as *const Self::Impl as *const *const ::core::ffi::c_void) .sub(#offset_of_this_in_pointers_token) as *const Self) } + + fn to_object(&self) -> ::windows_core::ComObject { + self.count.add_ref(); + unsafe { + ::windows_core::ComObject::from_raw( + ::core::ptr::NonNull::new_unchecked(self as *const Self as *mut Self) + ) + } + } + + const INNER_OFFSET_IN_POINTERS: usize = #offset_of_this_in_pointers_token; } impl #generics #original_ident::#generics where #constraints { @@ -341,7 +393,8 @@ struct ImplementType { impl ImplementType { fn to_ident(&self) -> proc_macro2::TokenStream { - let type_name = syn::parse_str::(&self.type_name).expect("Invalid token stream"); + let type_name = syn::parse_str::(&self.type_name) + .expect("Invalid token stream"); let generics = self.generics.iter().map(|g| g.to_ident()); quote! { #type_name<#(#generics,)*> } } @@ -383,7 +436,11 @@ impl ImplementAttributes { Ok(()) } - fn walk_implement(&mut self, tree: &UseTree2, namespace: &mut String) -> syn::parse::Result<()> { + fn walk_implement( + &mut self, + tree: &UseTree2, + namespace: &mut String, + ) -> syn::parse::Result<()> { match tree { UseTree2::Path(input) => { if !namespace.is_empty() { @@ -439,9 +496,15 @@ impl UseTree2 { generics.push(g.to_element_type(&mut String::new())?); } - Ok(ImplementType { type_name, generics }) + Ok(ImplementType { + type_name, + generics, + }) } - UseTree2::Group(input) => Err(syn::parse::Error::new(input.brace_token.span.join(), "Syntax not supported")), + UseTree2::Group(input) => Err(syn::parse::Error::new( + input.brace_token.span.join(), + "Syntax not supported", + )), _ => unimplemented!(), } } @@ -470,10 +533,16 @@ impl syn::parse::Parse for UseTree2 { let ident = input.call(syn::Ident::parse_any)?; if input.peek(syn::Token![::]) { input.parse::()?; - Ok(UseTree2::Path(UsePath2 { ident, tree: Box::new(input.parse()?) })) + Ok(UseTree2::Path(UsePath2 { + ident, + tree: Box::new(input.parse()?), + })) } else if input.peek(syn::Token![=]) { if ident != "TrustLevel" { - return Err(syn::parse::Error::new(ident.span(), "Unrecognized key-value pair")); + return Err(syn::parse::Error::new( + ident.span(), + "Unrecognized key-value pair", + )); } input.parse::()?; let span = input.span(); @@ -481,7 +550,10 @@ impl syn::parse::Parse for UseTree2 { match value.to_string().as_str() { "Partial" => Ok(UseTree2::TrustLevel(1)), "Full" => Ok(UseTree2::TrustLevel(2)), - _ => Err(syn::parse::Error::new(span, "`TrustLevel` must be `Partial` or `Full`")), + _ => Err(syn::parse::Error::new( + span, + "`TrustLevel` must be `Partial` or `Full`", + )), } } else { let generics = if input.peek(syn::Token![<]) { diff --git a/crates/libs/interface/src/lib.rs b/crates/libs/interface/src/lib.rs index b2f38b310a..e33379a921 100644 --- a/crates/libs/interface/src/lib.rs +++ b/crates/libs/interface/src/lib.rs @@ -30,7 +30,10 @@ use syn::spanned::Spanned; /// } /// ``` #[proc_macro_attribute] -pub fn interface(attributes: proc_macro::TokenStream, original_type: proc_macro::TokenStream) -> proc_macro::TokenStream { +pub fn interface( + attributes: proc_macro::TokenStream, + original_type: proc_macro::TokenStream, +) -> proc_macro::TokenStream { let guid = syn::parse_macro_input!(attributes as Guid); let interface = syn::parse_macro_input!(original_type as Interface); let tokens = match interface.gen_tokens(&guid) { @@ -208,9 +211,24 @@ impl Interface { }) .collect::>(); - let parent_vtable_generics = if self.parent_is_iunknown() { quote!(Identity, OFFSET) } else { quote!(Identity, Impl, OFFSET) }; + let parent_vtable_generics = if self.parent_is_iunknown() { + quote!(Identity, OFFSET) + } else { + quote!(Identity, Impl, OFFSET) + }; let parent_vtable = self.parent_vtable(); + // or_parent_matches will be `|| parent::matches(iid)` if this interface inherits from another + // interface (except for IUnknown) or will be empty if this is not applicable. This is what allows + // QueryInterface to work correctly for all interfaces in an inheritance chain, e.g. + // IFoo3 derives from IFoo2 derives from IFoo. + // + // We avoid matching IUnknown because object identity depends on the uniqueness of the IUnknown pointer. + let or_parent_matches = match parent_vtable.as_ref() { + Some(parent) if !self.parent_is_iunknown() => quote! (|| <#parent>::matches(iid)), + _ => quote!(), + }; + let functions = self .methods .iter() @@ -237,8 +255,11 @@ impl Interface { quote! { unsafe extern "system" fn #name, Impl: #trait_name, const OFFSET: isize>(this: *mut ::core::ffi::c_void, #(#args),*) #ret { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; - let this = (*this).get_impl(); - this.#name(#(#params),*).into() + let this_impl: &Impl = (*this).get_impl(); + // We use explicit so that we can select the correct method + // for situations where IFoo3 derives from IFoo2 and both declare a method with + // the same name. + ::#name(this_impl, #(#params),*).into() } } } else { @@ -284,8 +305,10 @@ impl Interface { Self { base__: #parent_vtable::new::<#parent_vtable_generics>(), #(#entries),* } } - pub fn matches(iid: &windows_core::GUID) -> bool { - iid == &<#name as ::windows_core::Interface>::IID + #[inline(always)] + pub fn matches(iid: &::windows_core::GUID) -> bool { + *iid == <#name as ::windows_core::Interface>::IID + #or_parent_matches } } } @@ -345,7 +368,7 @@ impl Interface { impl ::core::cmp::Eq for #name {} impl ::core::fmt::Debug for #name { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple(#name_string).field(&self.0).finish() + f.debug_tuple(#name_string).field(&::windows_core::Interface::as_raw(self)).finish() } } } @@ -378,7 +401,11 @@ impl Interface { fn parent_path(&self) -> Vec { if let Some(parent) = &self.parent { - parent.segments.iter().map(|segment| segment.ident.clone()).collect() + parent + .segments + .iter() + .map(|segment| segment.ident.clone()) + .collect() } else { vec![] } @@ -422,7 +449,13 @@ impl syn::parse::Parse for Interface { while !content.is_empty() { methods.push(content.parse::()?); } - Ok(Self { visibility, methods, name, parent, docs }) + Ok(Self { + visibility, + methods, + name, + parent, + docs, + }) } } @@ -443,14 +476,32 @@ impl Guid { syn::LitInt::new(&format!("0x{num}"), proc_macro2::Span::call_site()) } - fn ensure_length(part: Option<&str>, index: usize, length: usize, span: proc_macro2::Span) -> syn::Result { + fn ensure_length( + part: Option<&str>, + index: usize, + length: usize, + span: proc_macro2::Span, + ) -> syn::Result { let part = match part { Some(p) => p, - None => return Err(syn::Error::new(span, format!("The IID missing part at index {index}"))), + None => { + return Err(syn::Error::new( + span, + format!("The IID missing part at index {index}"), + )) + } }; if part.len() != length { - return Err(syn::Error::new(span, format!("The IID part at index {} must be {} characters long but was {} characters", index, length, part.len()))); + return Err(syn::Error::new( + span, + format!( + "The IID part at index {} must be {} characters long but was {} characters", + index, + length, + part.len() + ), + )); } Ok(part.to_owned()) @@ -459,7 +510,13 @@ impl Guid { if let Some(value) = &self.0 { let guid_value = value.value(); let mut delimited = guid_value.split('-').fuse(); - let chunks = [ensure_length(delimited.next(), 0, 8, value.span())?, ensure_length(delimited.next(), 1, 4, value.span())?, ensure_length(delimited.next(), 2, 4, value.span())?, ensure_length(delimited.next(), 3, 4, value.span())?, ensure_length(delimited.next(), 4, 12, value.span())?]; + let chunks = [ + ensure_length(delimited.next(), 0, 8, value.span())?, + ensure_length(delimited.next(), 1, 4, value.span())?, + ensure_length(delimited.next(), 2, 4, value.span())?, + ensure_length(delimited.next(), 3, 4, value.span())?, + ensure_length(delimited.next(), 4, 12, value.span())?, + ]; let data1 = hex_lit(&chunks[0]); let data2 = hex_lit(&chunks[1]); @@ -624,7 +681,10 @@ impl syn::parse::Parse for InterfaceMethod { unexpected_token!(sig.asyncness, "async declaration"); unexpected_token!(sig.generics.params.iter().next(), "generics declaration"); unexpected_token!(sig.constness, "const declaration"); - expected_token!(sig.receiver(), "the method to have &self as its first argument"); + expected_token!( + sig.receiver(), + "the method to have &self as its first argument" + ); unexpected_token!(sig.variadic, "variadic args"); let args = sig .inputs @@ -633,11 +693,22 @@ impl syn::parse::Parse for InterfaceMethod { syn::FnArg::Receiver(_) => None, syn::FnArg::Typed(p) => Some(p), }) - .map(|p| Ok(InterfaceMethodArg { ty: p.ty, pat: p.pat })) + .map(|p| { + Ok(InterfaceMethodArg { + ty: p.ty, + pat: p.pat, + }) + }) .collect::, syn::Error>>()?; let ret = sig.output; - Ok(InterfaceMethod { name: sig.ident, visibility, args, ret, docs }) + Ok(InterfaceMethod { + name: sig.ident, + visibility, + args, + ret, + docs, + }) } } diff --git a/crates/libs/metadata/src/bindings.rs b/crates/libs/metadata/src/bindings.rs index da834fabba..f96aba5f00 100644 --- a/crates/libs/metadata/src/bindings.rs +++ b/crates/libs/metadata/src/bindings.rs @@ -1,4 +1,10 @@ -#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] pub type CorElementType = u8; pub const ELEMENT_TYPE_ARRAY: CorElementType = 20u8; pub const ELEMENT_TYPE_BOOLEAN: CorElementType = 2u8; diff --git a/crates/libs/metadata/src/blob.rs b/crates/libs/metadata/src/blob.rs index 398d5fb3b3..204151bac7 100644 --- a/crates/libs/metadata/src/blob.rs +++ b/crates/libs/metadata/src/blob.rs @@ -24,7 +24,13 @@ impl Blob { } else if self[0] & 0xC0 == 0x80 { ((((self[0] & 0x3F) as usize) << 8) | self[1] as usize, 2) } else { - ((((self[0] & 0x1F) as usize) << 24) | (self[1] as usize) << 16 | (self[2] as usize) << 8 | self[3] as usize, 4) + ( + (((self[0] & 0x1F) as usize) << 24) + | (self[1] as usize) << 16 + | (self[2] as usize) << 8 + | self[3] as usize, + 4, + ) } } @@ -68,10 +74,16 @@ impl Blob { pub fn read_string(self) -> String { let slice = self.slice; if slice.as_ptr().align_offset(std::mem::align_of::()) > 0 { - let slice = slice.chunks_exact(2).take(slice.len() / 2).map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap())).collect::>(); + let slice = slice + .chunks_exact(2) + .take(slice.len() / 2) + .map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap())) + .collect::>(); String::from_utf16_lossy(&slice) } else { - let slice = unsafe { std::slice::from_raw_parts(slice.as_ptr() as *const u16, slice.len() / 2) }; + let slice = unsafe { + std::slice::from_raw_parts(slice.as_ptr() as *const u16, slice.len() / 2) + }; String::from_utf16_lossy(slice) } } diff --git a/crates/libs/metadata/src/file.rs b/crates/libs/metadata/src/file.rs index 3838c39a8f..869a1297d9 100644 --- a/crates/libs/metadata/src/file.rs +++ b/crates/libs/metadata/src/file.rs @@ -44,11 +44,19 @@ unsafe impl Sync for File {} impl File { pub fn new(bytes: Vec) -> Option { - let mut result = File { bytes, reader: std::ptr::null(), strings: 0, blobs: 0, tables: Default::default() }; + let mut result = File { + bytes, + reader: std::ptr::null(), + strings: 0, + blobs: 0, + tables: Default::default(), + }; let dos = result.bytes.view_as::(0)?; - if dos.e_magic != IMAGE_DOS_SIGNATURE || result.bytes.copy_as::(dos.e_lfanew as usize)? != IMAGE_NT_SIGNATURE { + if dos.e_magic != IMAGE_DOS_SIGNATURE + || result.bytes.copy_as::(dos.e_lfanew as usize)? != IMAGE_NT_SIGNATURE + { return None; } @@ -59,23 +67,47 @@ impl File { let (com_virtual_address, sections) = match result.bytes.copy_as::(optional_offset)? { IMAGE_NT_OPTIONAL_HDR32_MAGIC => { - let optional = result.bytes.view_as::(optional_offset)?; - (optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize].VirtualAddress, result.bytes.view_as_slice_of::(optional_offset + std::mem::size_of::(), file.NumberOfSections as usize)?) + let optional = result + .bytes + .view_as::(optional_offset)?; + ( + optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize] + .VirtualAddress, + result.bytes.view_as_slice_of::( + optional_offset + std::mem::size_of::(), + file.NumberOfSections as usize, + )?, + ) } IMAGE_NT_OPTIONAL_HDR64_MAGIC => { - let optional = result.bytes.view_as::(optional_offset)?; - (optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize].VirtualAddress, result.bytes.view_as_slice_of::(optional_offset + std::mem::size_of::(), file.NumberOfSections as usize)?) + let optional = result + .bytes + .view_as::(optional_offset)?; + ( + optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize] + .VirtualAddress, + result.bytes.view_as_slice_of::( + optional_offset + std::mem::size_of::(), + file.NumberOfSections as usize, + )?, + ) } _ => return None, }; - let clr = result.bytes.view_as::(offset_from_rva(section_from_rva(sections, com_virtual_address)?, com_virtual_address))?; + let clr = result.bytes.view_as::(offset_from_rva( + section_from_rva(sections, com_virtual_address)?, + com_virtual_address, + ))?; if clr.cb != std::mem::size_of::() as u32 { return None; } - let metadata_offset = offset_from_rva(section_from_rva(sections, clr.MetaData.VirtualAddress)?, clr.MetaData.VirtualAddress); + let metadata_offset = offset_from_rva( + section_from_rva(sections, clr.MetaData.VirtualAddress)?, + clr.MetaData.VirtualAddress, + ); let metadata = result.bytes.view_as::(metadata_offset)?; if metadata.signature != METADATA_SIGNATURE { @@ -86,7 +118,10 @@ impl File { let mut view = metadata_offset + metadata.length as usize + 20; let mut tables_data: (usize, usize) = (0, 0); - for _ in 0..result.bytes.copy_as::(metadata_offset + metadata.length as usize + 18)? { + for _ in 0..result + .bytes + .copy_as::(metadata_offset + metadata.length as usize + 18)? + { let stream_offset = result.bytes.copy_as::(view)? as usize; let stream_len = result.bytes.copy_as::(view + 4)? as usize; let stream_name = result.bytes.view_as_str(view + 8)?; @@ -188,18 +223,55 @@ impl File { } let tables = &result.tables; - let type_def_or_ref = coded_index_size(&[tables[TypeDef::TABLE].len, tables[TypeRef::TABLE].len, tables[TypeSpec::TABLE].len]); - let has_constant = coded_index_size(&[tables[Field::TABLE].len, tables[Param::TABLE].len, unused_property.len]); - let has_field_marshal = coded_index_size(&[tables[Field::TABLE].len, tables[Param::TABLE].len]); - let has_decl_security = coded_index_size(&[tables[TypeDef::TABLE].len, tables[MethodDef::TABLE].len, unused_assembly.len]); - let member_ref_parent = coded_index_size(&[tables[TypeDef::TABLE].len, tables[TypeRef::TABLE].len, tables[ModuleRef::TABLE].len, tables[MethodDef::TABLE].len, tables[TypeSpec::TABLE].len]); + let type_def_or_ref = coded_index_size(&[ + tables[TypeDef::TABLE].len, + tables[TypeRef::TABLE].len, + tables[TypeSpec::TABLE].len, + ]); + let has_constant = coded_index_size(&[ + tables[Field::TABLE].len, + tables[Param::TABLE].len, + unused_property.len, + ]); + let has_field_marshal = + coded_index_size(&[tables[Field::TABLE].len, tables[Param::TABLE].len]); + let has_decl_security = coded_index_size(&[ + tables[TypeDef::TABLE].len, + tables[MethodDef::TABLE].len, + unused_assembly.len, + ]); + let member_ref_parent = coded_index_size(&[ + tables[TypeDef::TABLE].len, + tables[TypeRef::TABLE].len, + tables[ModuleRef::TABLE].len, + tables[MethodDef::TABLE].len, + tables[TypeSpec::TABLE].len, + ]); let has_semantics = coded_index_size(&[unused_event.len, unused_property.len]); - let method_def_or_ref = coded_index_size(&[tables[MethodDef::TABLE].len, tables[MemberRef::TABLE].len]); - let member_forwarded = coded_index_size(&[tables[Field::TABLE].len, tables[MethodDef::TABLE].len]); - let implementation = coded_index_size(&[unused_file.len, tables[AssemblyRef::TABLE].len, unused_exported_type.len]); - let custom_attribute_type = coded_index_size(&[tables[MethodDef::TABLE].len, tables[MemberRef::TABLE].len, unused_empty.len, unused_empty.len, unused_empty.len]); - let resolution_scope = coded_index_size(&[tables[Module::TABLE].len, tables[ModuleRef::TABLE].len, tables[AssemblyRef::TABLE].len, tables[TypeRef::TABLE].len]); - let type_or_method_def = coded_index_size(&[tables[TypeDef::TABLE].len, tables[MethodDef::TABLE].len]); + let method_def_or_ref = + coded_index_size(&[tables[MethodDef::TABLE].len, tables[MemberRef::TABLE].len]); + let member_forwarded = + coded_index_size(&[tables[Field::TABLE].len, tables[MethodDef::TABLE].len]); + let implementation = coded_index_size(&[ + unused_file.len, + tables[AssemblyRef::TABLE].len, + unused_exported_type.len, + ]); + let custom_attribute_type = coded_index_size(&[ + tables[MethodDef::TABLE].len, + tables[MemberRef::TABLE].len, + unused_empty.len, + unused_empty.len, + unused_empty.len, + ]); + let resolution_scope = coded_index_size(&[ + tables[Module::TABLE].len, + tables[ModuleRef::TABLE].len, + tables[AssemblyRef::TABLE].len, + tables[TypeRef::TABLE].len, + ]); + let type_or_method_def = + coded_index_size(&[tables[TypeDef::TABLE].len, tables[MethodDef::TABLE].len]); let has_custom_attribute = coded_index_size(&[ tables[MethodDef::TABLE].len, @@ -225,43 +297,190 @@ impl File { unused_method_spec.len, ]); - unused_assembly.set_columns(4, 8, 4, blob_index_size, string_index_size, string_index_size); + unused_assembly.set_columns( + 4, + 8, + 4, + blob_index_size, + string_index_size, + string_index_size, + ); unused_assembly_os.set_columns(4, 4, 4, 0, 0, 0); unused_assembly_processor.set_columns(4, 0, 0, 0, 0, 0); - result.tables[AssemblyRef::TABLE].set_columns(8, 4, blob_index_size, string_index_size, string_index_size, blob_index_size); - unused_assembly_ref_os.set_columns(4, 4, 4, result.tables[AssemblyRef::TABLE].index_width(), 0, 0); - unused_assembly_ref_processor.set_columns(4, result.tables[AssemblyRef::TABLE].index_width(), 0, 0, 0, 0); - result.tables[ClassLayout::TABLE].set_columns(2, 4, result.tables[TypeDef::TABLE].index_width(), 0, 0, 0); + result.tables[AssemblyRef::TABLE].set_columns( + 8, + 4, + blob_index_size, + string_index_size, + string_index_size, + blob_index_size, + ); + unused_assembly_ref_os.set_columns( + 4, + 4, + 4, + result.tables[AssemblyRef::TABLE].index_width(), + 0, + 0, + ); + unused_assembly_ref_processor.set_columns( + 4, + result.tables[AssemblyRef::TABLE].index_width(), + 0, + 0, + 0, + 0, + ); + result.tables[ClassLayout::TABLE].set_columns( + 2, + 4, + result.tables[TypeDef::TABLE].index_width(), + 0, + 0, + 0, + ); result.tables[Constant::TABLE].set_columns(2, has_constant, blob_index_size, 0, 0, 0); - result.tables[Attribute::TABLE].set_columns(has_custom_attribute, custom_attribute_type, blob_index_size, 0, 0, 0); + result.tables[Attribute::TABLE].set_columns( + has_custom_attribute, + custom_attribute_type, + blob_index_size, + 0, + 0, + 0, + ); unused_decl_security.set_columns(2, has_decl_security, blob_index_size, 0, 0, 0); - unused_event_map.set_columns(result.tables[TypeDef::TABLE].index_width(), unused_event.index_width(), 0, 0, 0, 0); + unused_event_map.set_columns( + result.tables[TypeDef::TABLE].index_width(), + unused_event.index_width(), + 0, + 0, + 0, + 0, + ); unused_event.set_columns(2, string_index_size, type_def_or_ref, 0, 0, 0); - unused_exported_type.set_columns(4, 4, string_index_size, string_index_size, implementation, 0); + unused_exported_type.set_columns( + 4, + 4, + string_index_size, + string_index_size, + implementation, + 0, + ); result.tables[Field::TABLE].set_columns(2, string_index_size, blob_index_size, 0, 0, 0); unused_field_layout.set_columns(4, result.tables[Field::TABLE].index_width(), 0, 0, 0, 0); unused_field_marshal.set_columns(has_field_marshal, blob_index_size, 0, 0, 0, 0); unused_field_rva.set_columns(4, result.tables[Field::TABLE].index_width(), 0, 0, 0, 0); unused_file.set_columns(4, string_index_size, blob_index_size, 0, 0, 0); - result.tables[GenericParam::TABLE].set_columns(2, 2, type_or_method_def, string_index_size, 0, 0); - unused_generic_param_constraint.set_columns(result.tables[GenericParam::TABLE].index_width(), type_def_or_ref, 0, 0, 0, 0); - result.tables[ImplMap::TABLE].set_columns(2, member_forwarded, string_index_size, result.tables[ModuleRef::TABLE].index_width(), 0, 0); - result.tables[InterfaceImpl::TABLE].set_columns(result.tables[TypeDef::TABLE].index_width(), type_def_or_ref, 0, 0, 0, 0); + result.tables[GenericParam::TABLE].set_columns( + 2, + 2, + type_or_method_def, + string_index_size, + 0, + 0, + ); + unused_generic_param_constraint.set_columns( + result.tables[GenericParam::TABLE].index_width(), + type_def_or_ref, + 0, + 0, + 0, + 0, + ); + result.tables[ImplMap::TABLE].set_columns( + 2, + member_forwarded, + string_index_size, + result.tables[ModuleRef::TABLE].index_width(), + 0, + 0, + ); + result.tables[InterfaceImpl::TABLE].set_columns( + result.tables[TypeDef::TABLE].index_width(), + type_def_or_ref, + 0, + 0, + 0, + 0, + ); unused_manifest_resource.set_columns(4, 4, string_index_size, implementation, 0, 0); - result.tables[MemberRef::TABLE].set_columns(member_ref_parent, string_index_size, blob_index_size, 0, 0, 0); - result.tables[MethodDef::TABLE].set_columns(4, 2, 2, string_index_size, blob_index_size, result.tables[Param::TABLE].index_width()); - unused_method_impl.set_columns(result.tables[TypeDef::TABLE].index_width(), method_def_or_ref, method_def_or_ref, 0, 0, 0); - unused_method_semantics.set_columns(2, result.tables[MethodDef::TABLE].index_width(), has_semantics, 0, 0, 0); + result.tables[MemberRef::TABLE].set_columns( + member_ref_parent, + string_index_size, + blob_index_size, + 0, + 0, + 0, + ); + result.tables[MethodDef::TABLE].set_columns( + 4, + 2, + 2, + string_index_size, + blob_index_size, + result.tables[Param::TABLE].index_width(), + ); + unused_method_impl.set_columns( + result.tables[TypeDef::TABLE].index_width(), + method_def_or_ref, + method_def_or_ref, + 0, + 0, + 0, + ); + unused_method_semantics.set_columns( + 2, + result.tables[MethodDef::TABLE].index_width(), + has_semantics, + 0, + 0, + 0, + ); unused_method_spec.set_columns(method_def_or_ref, blob_index_size, 0, 0, 0, 0); - result.tables[Module::TABLE].set_columns(2, string_index_size, guid_index_size, guid_index_size, guid_index_size, 0); + result.tables[Module::TABLE].set_columns( + 2, + string_index_size, + guid_index_size, + guid_index_size, + guid_index_size, + 0, + ); result.tables[ModuleRef::TABLE].set_columns(string_index_size, 0, 0, 0, 0, 0); - result.tables[NestedClass::TABLE].set_columns(result.tables[TypeDef::TABLE].index_width(), result.tables[TypeDef::TABLE].index_width(), 0, 0, 0, 0); + result.tables[NestedClass::TABLE].set_columns( + result.tables[TypeDef::TABLE].index_width(), + result.tables[TypeDef::TABLE].index_width(), + 0, + 0, + 0, + 0, + ); result.tables[Param::TABLE].set_columns(2, 2, string_index_size, 0, 0, 0); unused_property.set_columns(2, string_index_size, blob_index_size, 0, 0, 0); - unused_property_map.set_columns(result.tables[TypeDef::TABLE].index_width(), unused_property.index_width(), 0, 0, 0, 0); + unused_property_map.set_columns( + result.tables[TypeDef::TABLE].index_width(), + unused_property.index_width(), + 0, + 0, + 0, + 0, + ); unused_standalone_sig.set_columns(blob_index_size, 0, 0, 0, 0, 0); - result.tables[TypeDef::TABLE].set_columns(4, string_index_size, string_index_size, type_def_or_ref, result.tables[Field::TABLE].index_width(), result.tables[MethodDef::TABLE].index_width()); - result.tables[TypeRef::TABLE].set_columns(resolution_scope, string_index_size, string_index_size, 0, 0, 0); + result.tables[TypeDef::TABLE].set_columns( + 4, + string_index_size, + string_index_size, + type_def_or_ref, + result.tables[Field::TABLE].index_width(), + result.tables[MethodDef::TABLE].index_width(), + ); + result.tables[TypeRef::TABLE].set_columns( + resolution_scope, + string_index_size, + string_index_size, + 0, + 0, + 0, + ); result.tables[TypeSpec::TABLE].set_columns(blob_index_size, 0, 0, 0, 0, 0); result.tables[Module::TABLE].set_data(&mut view); @@ -316,7 +535,14 @@ impl File { } } - pub fn lower_bound_of(&self, table: usize, mut first: usize, last: usize, column: usize, value: usize) -> usize { + pub fn lower_bound_of( + &self, + table: usize, + mut first: usize, + last: usize, + column: usize, + value: usize, + ) -> usize { let mut count = last - first; while count > 0 { let count2 = count / 2; @@ -331,7 +557,14 @@ impl File { first } - pub fn upper_bound_of(&self, table: usize, mut first: usize, last: usize, column: usize, value: usize) -> usize { + pub fn upper_bound_of( + &self, + table: usize, + mut first: usize, + last: usize, + column: usize, + value: usize, + ) -> usize { let mut count = last - first; while count > 0 { let count2 = count / 2; @@ -352,7 +585,9 @@ impl File { } fn section_from_rva(sections: &[IMAGE_SECTION_HEADER], rva: u32) -> Option<&IMAGE_SECTION_HEADER> { - sections.iter().find(|&s| rva >= s.VirtualAddress && rva < s.VirtualAddress + unsafe { s.Misc.VirtualSize }) + sections.iter().find(|&s| { + rva >= s.VirtualAddress && rva < s.VirtualAddress + unsafe { s.Misc.VirtualSize } + }) } fn offset_from_rva(section: &IMAGE_SECTION_HEADER, rva: u32) -> usize { @@ -374,7 +609,12 @@ impl View for [u8] { } fn view_as_slice_of(&self, offset: usize, len: usize) -> Option<&[T]> { - unsafe { Some(std::slice::from_raw_parts(self.is_proper_length_and_alignment(offset, len)?, len)) } + unsafe { + Some(std::slice::from_raw_parts( + self.is_proper_length_and_alignment(offset, len)?, + len, + )) + } } fn copy_as(&self, offset: usize) -> Option { @@ -382,7 +622,11 @@ impl View for [u8] { unsafe { let mut data = std::mem::MaybeUninit::zeroed().assume_init(); - core::ptr::copy_nonoverlapping(self[offset..].as_ptr(), &mut data as *mut T as *mut u8, std::mem::size_of::()); + core::ptr::copy_nonoverlapping( + self[offset..].as_ptr(), + &mut data as *mut T as *mut u8, + std::mem::size_of::(), + ); Some(data) } } diff --git a/crates/libs/metadata/src/lib.rs b/crates/libs/metadata/src/lib.rs index 870be4c649..c7ef6c1f16 100644 --- a/crates/libs/metadata/src/lib.rs +++ b/crates/libs/metadata/src/lib.rs @@ -106,7 +106,9 @@ pub struct MethodDefSig { impl MethodDefSig { pub fn size(&self) -> usize { - self.params.iter().fold(0, |sum, param| sum + std::cmp::max(4, param.size())) + self.params + .iter() + .fold(0, |sum, param| sum + std::cmp::max(4, param.size())) } } diff --git a/crates/libs/metadata/src/reader.rs b/crates/libs/metadata/src/reader.rs index ee661966ba..e9aa90287b 100644 --- a/crates/libs/metadata/src/reader.rs +++ b/crates/libs/metadata/src/reader.rs @@ -30,8 +30,18 @@ impl Reader { Self::filter(files, &[], &[], &config) } - pub fn filter(files: Vec, include: &[&str], exclude: &[&str], config: &BTreeMap<&str, &str>) -> &'static Self { - let reader: &'static mut Reader = Box::leak(Box::new(Self { items: Default::default(), nested: Default::default(), filter: Filter::new(include, exclude), sys: config.contains_key("sys") })); + pub fn filter( + files: Vec, + include: &[&str], + exclude: &[&str], + config: &BTreeMap<&str, &str>, + ) -> &'static Self { + let reader: &'static mut Reader = Box::leak(Box::new(Self { + items: Default::default(), + nested: Default::default(), + filter: Filter::new(include, exclude), + sys: config.contains_key("sys"), + })); for mut file in files { file.reader = reader as *mut Reader; @@ -49,19 +59,37 @@ impl Reader { if name == "Apis" { for method in def.methods() { - namespace_items.entry(method.name()).or_default().push(Item::Fn(method, namespace)); + namespace_items + .entry(method.name()) + .or_default() + .push(Item::Fn(method, namespace)); } for field in def.fields() { - namespace_items.entry(field.name()).or_default().push(Item::Const(field)); + namespace_items + .entry(field.name()) + .or_default() + .push(Item::Const(field)); } } else { - namespace_items.entry(name).or_default().push(Item::Type(def)); + namespace_items + .entry(name) + .or_default() + .push(Item::Type(def)); // TODO: these should all be fields on the Apis class so we don't have to go looking for all of these as well. - if def.extends() == Some(TypeName::Enum) && !def.flags().contains(TypeAttributes::WindowsRuntime) && !def.has_attribute("ScopedEnumAttribute") { - for field in def.fields().filter(|field| field.flags().contains(FieldAttributes::Literal)) { - namespace_items.entry(field.name()).or_default().push(Item::Const(field)); + if def.extends() == Some(TypeName::Enum) + && !def.flags().contains(TypeAttributes::WindowsRuntime) + && !def.has_attribute("ScopedEnumAttribute") + { + for field in def + .fields() + .filter(|field| field.flags().contains(FieldAttributes::Literal)) + { + namespace_items + .entry(field.name()) + .or_default() + .push(Item::Const(field)); } } } @@ -69,7 +97,11 @@ impl Reader { for key in file.table::() { let inner = key.inner(); - reader.nested.entry(key.outer()).or_default().insert(inner.name(), inner); + reader + .nested + .entry(key.outer()) + .or_default() + .insert(inner.name(), inner); } } @@ -85,15 +117,39 @@ impl Reader { } pub fn items(&self) -> impl Iterator + '_ { - self.items.iter().filter(move |(namespace, _)| self.filter.includes_namespace(namespace)).flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| self.filter.includes_type_name(namespace, name))).flat_map(move |(_, items)| items).cloned() + self.items + .iter() + .filter(move |(namespace, _)| self.filter.includes_namespace(namespace)) + .flat_map(move |(namespace, items)| { + items + .iter() + .filter(move |(name, _)| self.filter.includes_type_name(namespace, name)) + }) + .flat_map(move |(_, items)| items) + .cloned() } pub fn namespace_items(&self, namespace: &str) -> impl Iterator + '_ { - self.items.get_key_value(namespace).into_iter().flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| self.filter.includes_type_name(namespace, name))).flat_map(move |(_, items)| items).cloned() + self.items + .get_key_value(namespace) + .into_iter() + .flat_map(move |(namespace, items)| { + items + .iter() + .filter(move |(name, _)| self.filter.includes_type_name(namespace, name)) + }) + .flat_map(move |(_, items)| items) + .cloned() } pub fn unused(&self) -> impl Iterator + '_ { - self.filter.0.iter().filter_map(|(name, _)| if self.is_unused(name) { Some(name.as_str()) } else { None }) + self.filter.0.iter().filter_map(|(name, _)| { + if self.is_unused(name) { + Some(name.as_str()) + } else { + None + } + }) } fn is_unused(&self, filter: &str) -> bool { @@ -104,14 +160,21 @@ impl Reader { // Match type names if let Some((namespace, name)) = filter.rsplit_once('.') { - if self.items.get(namespace).is_some_and(|items| items.contains_key(name)) { + if self + .items + .get(namespace) + .is_some_and(|items| items.contains_key(name)) + { return false; } } // Match empty parent namespaces for namespace in self.items.keys() { - if namespace.len() > filter.len() && namespace.starts_with(filter) && namespace.as_bytes()[filter.len()] == b'.' { + if namespace.len() > filter.len() + && namespace.starts_with(filter) + && namespace.as_bytes()[filter.len()] == b'.' + { return false; } } @@ -129,15 +192,35 @@ impl Reader { } pub fn get_type_def(&self, namespace: &str, name: &str) -> impl Iterator + '_ { - self.get_item(namespace, name).filter_map(|item| if let Item::Type(def) = item { Some(def) } else { None }) + self.get_item(namespace, name).filter_map(|item| { + if let Item::Type(def) = item { + Some(def) + } else { + None + } + }) } - pub fn get_method_def(&self, namespace: &str, name: &str) -> impl Iterator + '_ { - self.get_item(namespace, name).filter_map(|item| if let Item::Fn(def, namespace) = item { Some((def, namespace)) } else { None }) + pub fn get_method_def( + &self, + namespace: &str, + name: &str, + ) -> impl Iterator + '_ { + self.get_item(namespace, name).filter_map(|item| { + if let Item::Fn(def, namespace) = item { + Some((def, namespace)) + } else { + None + } + }) } pub fn nested_types(&self, type_def: TypeDef) -> impl Iterator + '_ { - self.nested.get(&type_def).map(|map| map.values().copied()).into_iter().flatten() + self.nested + .get(&type_def) + .map(|map| map.values().copied()) + .into_iter() + .flatten() } pub fn remap_type(&self, name: TypeName) -> Option { @@ -169,7 +252,12 @@ impl Reader { } } - pub fn type_from_ref(&self, code: TypeDefOrRef, enclosing: Option, generics: &[Type]) -> Type { + pub fn type_from_ref( + &self, + code: TypeDefOrRef, + enclosing: Option, + generics: &[Type], + ) -> Type { if let TypeDefOrRef::TypeSpec(def) = code { let mut blob = def.blob(0); return self.type_from_blob_impl(&mut blob, None, generics); @@ -190,23 +278,38 @@ impl Reader { if full_name.namespace().is_empty() { let nested = &self.nested[&outer]; let Some(inner) = nested.get(full_name.name()) else { - panic!("Nested type not found: {}.{}", outer.type_name(), full_name.name()); + panic!( + "Nested type not found: {}.{}", + outer.type_name(), + full_name.name() + ); }; return Type::TypeDef(*inner, Vec::new()); } } // TODO: this needs to just return a TypeRef and avoid resolving as its too early to bake in the type - if let Some(def) = self.get_type_def(full_name.namespace(), full_name.name()).next() { + if let Some(def) = self + .get_type_def(full_name.namespace(), full_name.name()) + .next() + { Type::TypeDef(def, Vec::new()) } else { Type::Name(full_name) } } - pub fn type_from_blob(&self, blob: &mut Blob, enclosing: Option, generics: &[Type]) -> Type { + pub fn type_from_blob( + &self, + blob: &mut Blob, + enclosing: Option, + generics: &[Type], + ) -> Type { // Used by WinRT to indicate that a struct input parameter is passed by reference rather than by value on the ABI. - let is_const = blob.read_modifiers().iter().any(|def| def.type_name() == TypeName::IsConst); + let is_const = blob + .read_modifiers() + .iter() + .any(|def| def.type_name() == TypeName::IsConst); // Used by WinRT to indicate an output parameter, but there are other ways to determine this direction so here // it is only used to distinguish between slices and heap-allocated arrays. @@ -241,7 +344,12 @@ impl Reader { } } - fn type_from_blob_impl(&self, blob: &mut Blob, enclosing: Option, generics: &[Type]) -> Type { + fn type_from_blob_impl( + &self, + blob: &mut Blob, + enclosing: Option, + generics: &[Type], + ) -> Type { let code = blob.read_usize(); if let Some(code) = Type::from_code(code) { @@ -249,8 +357,15 @@ impl Reader { } match code as u8 { - ELEMENT_TYPE_VALUETYPE | ELEMENT_TYPE_CLASS => self.type_from_ref(TypeDefOrRef::decode(blob.file, blob.read_usize()), enclosing, generics), - ELEMENT_TYPE_VAR => generics.get(blob.read_usize()).unwrap_or(&Type::Void).clone(), + ELEMENT_TYPE_VALUETYPE | ELEMENT_TYPE_CLASS => self.type_from_ref( + TypeDefOrRef::decode(blob.file, blob.read_usize()), + enclosing, + generics, + ), + ELEMENT_TYPE_VAR => generics + .get(blob.read_usize()) + .unwrap_or(&Type::Void) + .clone(), ELEMENT_TYPE_ARRAY => { let kind = self.type_from_blob(blob, enclosing, generics); let _rank = blob.read_usize(); @@ -262,7 +377,10 @@ impl Reader { blob.read_usize(); // ELEMENT_TYPE_VALUETYPE or ELEMENT_TYPE_CLASS let type_name = TypeDefOrRef::decode(blob.file, blob.read_usize()).type_name(); - let def = self.get_type_def(type_name.namespace(), type_name.name()).next().unwrap_or_else(|| panic!("Type not found: {}", type_name)); + let def = self + .get_type_def(type_name.namespace(), type_name.name()) + .next() + .unwrap_or_else(|| panic!("Type not found: {}", type_name)); let mut args = Vec::with_capacity(blob.read_usize()); for _ in 0..args.capacity() { diff --git a/crates/libs/metadata/src/row.rs b/crates/libs/metadata/src/row.rs index 4b99f56851..7e329b8b0a 100644 --- a/crates/libs/metadata/src/row.rs +++ b/crates/libs/metadata/src/row.rs @@ -12,7 +12,10 @@ impl Row { } fn next(&self) -> Self { - Self { file: self.file, index: self.index + 1 } + Self { + file: self.file, + index: self.index + 1, + } } } @@ -46,7 +49,10 @@ pub trait AsRow: Copy { let file = self.file(); let offset = file.strings + self.usize(column); let bytes = &file.bytes[offset..]; - let nul_pos = bytes.iter().position(|&c| c == 0).expect("expected null-terminated C-string"); + let nul_pos = bytes + .iter() + .position(|&c| c == 0) + .expect("expected null-terminated C-string"); std::str::from_utf8(&bytes[..nul_pos]).expect("expected valid utf-8 C-string") } @@ -84,7 +90,11 @@ pub trait AsRow: Copy { let file = self.file(); let first = self.usize(column) - 1; let next = self.next(); - let last = if next.index() < file.tables[Self::TABLE].len { next.usize(column) - 1 } else { file.tables[R::TABLE].len }; + let last = if next.index() < file.tables[Self::TABLE].len { + next.usize(column) - 1 + } else { + file.tables[R::TABLE].len + }; RowIterator::new(file, first..last) } @@ -132,7 +142,11 @@ pub struct RowIterator { impl RowIterator { pub fn new(file: &'static File, rows: std::ops::Range) -> Self { - Self { file, rows, phantom: std::marker::PhantomData } + Self { + file, + rows, + phantom: std::marker::PhantomData, + } } } @@ -140,7 +154,9 @@ impl Iterator for RowIterator { type Item = R; fn next(&mut self) -> Option { - self.rows.next().map(|row| R::from_row(Row::new(self.file, row))) + self.rows + .next() + .map(|row| R::from_row(Row::new(self.file, row))) } } diff --git a/crates/libs/metadata/src/tables.rs b/crates/libs/metadata/src/tables.rs index de2b86e2fb..73f23ed67c 100644 --- a/crates/libs/metadata/src/tables.rs +++ b/crates/libs/metadata/src/tables.rs @@ -88,7 +88,9 @@ impl Attribute { Type::U64 => Value::U64(values.read_u64()), Type::String => Value::String(values.read_str().to_string()), Type::Name(TypeName::Type) => Value::TypeName(TypeName::parse(values.read_str())), - Type::TypeDef(def, _) => Value::EnumDef(def, Box::new(values.read_integer(def.underlying_type()))), + Type::TypeDef(def, _) => { + Value::EnumDef(def, Box::new(values.read_integer(def.underlying_type()))) + } rest => unimplemented!("{rest:?}"), }; @@ -111,7 +113,10 @@ impl Attribute { 0x50 => Value::TypeName(TypeName::parse(values.read_str())), 0x55 => { let type_name = TypeName::parse(name); - let def = reader.get_type_def(type_name.namespace(), type_name.name()).next().expect("Type not found"); + let def = reader + .get_type_def(type_name.namespace(), type_name.name()) + .next() + .expect("Type not found"); name = values.read_str(); Value::EnumDef(def, Box::new(values.read_integer(def.underlying_type()))) } @@ -168,7 +173,8 @@ impl Field { } pub fn constant(&self) -> Option { - self.equal_range(1, HasConstant::Field(*self).encode()).next() + self.equal_range(1, HasConstant::Field(*self).encode()) + .next() } // TODO: enclosing craziness is only needed for nested structs - get rid of those in riddle and this goes away. @@ -232,7 +238,13 @@ impl MemberRef { let params = blob.read_usize(); let return_type = reader.type_from_blob(&mut blob, None, &[]); - MethodDefSig { call_flags, return_type, params: (0..params).map(|_| reader.type_from_blob(&mut blob, None, &[])).collect() } + MethodDefSig { + call_flags, + return_type, + params: (0..params) + .map(|_| reader.type_from_blob(&mut blob, None, &[])) + .collect(), + } } } @@ -254,7 +266,8 @@ impl MethodDef { } pub fn impl_map(&self) -> Option { - self.equal_range(1, MemberForwarded::MethodDef(*self).encode()).next() + self.equal_range(1, MemberForwarded::MethodDef(*self).encode()) + .next() } pub fn module_name(&self) -> &'static str { @@ -268,7 +281,13 @@ impl MethodDef { let params = blob.read_usize(); let return_type = reader.type_from_blob(&mut blob, None, generics); - MethodDefSig { call_flags, return_type, params: (0..params).map(|_| reader.type_from_blob(&mut blob, None, generics)).collect() } + MethodDefSig { + call_flags, + return_type, + params: (0..params) + .map(|_| reader.type_from_blob(&mut blob, None, generics)) + .collect(), + } } } @@ -346,7 +365,9 @@ impl TypeDef { } pub fn enclosing_type(&self) -> Option { - self.equal_range::(0, self.index() + 1).next().map(|row| TypeDef(row.row(1))) + self.equal_range::(0, self.index() + 1) + .next() + .map(|row| TypeDef(row.row(1))) } pub fn class_layout(&self) -> Option { @@ -376,7 +397,10 @@ impl TypeDef { match self.kind() { TypeKind::Struct => { if self.flags().contains(TypeAttributes::ExplicitLayout) { - self.fields().map(|field| field.ty(Some(*self)).size()).max().unwrap_or(1) + self.fields() + .map(|field| field.ty(Some(*self)).size()) + .max() + .unwrap_or(1) } else { let mut sum = 0; for field in self.fields() { @@ -396,7 +420,11 @@ impl TypeDef { pub fn align(&self) -> usize { match self.kind() { - TypeKind::Struct => self.fields().map(|field| field.ty(Some(*self)).align()).max().unwrap_or(1), + TypeKind::Struct => self + .fields() + .map(|field| field.ty(Some(*self)).align()) + .max() + .unwrap_or(1), TypeKind::Enum => self.underlying_type().align(), _ => 4, } diff --git a/crates/libs/metadata/src/type.rs b/crates/libs/metadata/src/type.rs index dde508160d..f9599a5c99 100644 --- a/crates/libs/metadata/src/type.rs +++ b/crates/libs/metadata/src/type.rs @@ -69,7 +69,9 @@ impl Type { pub fn to_const_type(self) -> Self { match self { Self::MutPtr(kind, pointers) => Self::MutPtr(Box::new(kind.to_const_type()), pointers), - Self::ConstPtr(kind, pointers) => Self::ConstPtr(Box::new(kind.to_const_type()), pointers), + Self::ConstPtr(kind, pointers) => { + Self::ConstPtr(Box::new(kind.to_const_type()), pointers) + } Self::Name(TypeName::PSTR) => Self::Const(TypeName::PSTR), Self::Name(TypeName::PWSTR) => Self::Const(TypeName::PWSTR), _ => self, @@ -137,7 +139,10 @@ impl Type { /// Returns `true` if the `Type` is unsigned. pub fn is_unsigned(&self) -> bool { - matches!(self, Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::USize) + matches!( + self, + Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::USize + ) } /// Returns `true` if the `Type` is incomplete. diff --git a/crates/libs/metadata/src/type_name.rs b/crates/libs/metadata/src/type_name.rs index 708fa6e674..19160a7ad6 100644 --- a/crates/libs/metadata/src/type_name.rs +++ b/crates/libs/metadata/src/type_name.rs @@ -15,9 +15,11 @@ impl TypeName { pub const HResult: Self = Self("Windows.Foundation", "HResult"); pub const IAsyncAction: Self = Self("Windows.Foundation", "IAsyncAction"); - pub const IAsyncActionWithProgress: Self = Self("Windows.Foundation", "IAsyncActionWithProgress"); + pub const IAsyncActionWithProgress: Self = + Self("Windows.Foundation", "IAsyncActionWithProgress"); pub const IAsyncOperation: Self = Self("Windows.Foundation", "IAsyncOperation"); - pub const IAsyncOperationWithProgress: Self = Self("Windows.Foundation", "IAsyncOperationWithProgress"); + pub const IAsyncOperationWithProgress: Self = + Self("Windows.Foundation", "IAsyncOperationWithProgress"); pub const Matrix3x2: Self = Self("Windows.Foundation.Numerics", "Matrix3x2"); pub const Matrix4x4: Self = Self("Windows.Foundation.Numerics", "Matrix4x4"); @@ -38,19 +40,23 @@ impl TypeName { pub const NTSTATUS: Self = Self("Windows.Win32.Foundation", "NTSTATUS"); pub const RPC_STATUS: Self = Self("Windows.Win32.System.Rpc", "RPC_STATUS"); - pub const D2D_MATRIX_3X2_F: Self = Self("Windows.Win32.Graphics.Direct2D.Common", "D2D_MATRIX_3X2_F"); + pub const D2D_MATRIX_3X2_F: Self = + Self("Windows.Win32.Graphics.Direct2D.Common", "D2D_MATRIX_3X2_F"); pub const D3DMATRIX: Self = Self("Windows.Win32.Graphics.Direct3D", "D3DMATRIX"); pub const IUnknown: Self = Self("Windows.Win32.System.Com", "IUnknown"); pub const HSTRING: Self = Self("Windows.Win32.System.WinRT", "HSTRING"); pub const IInspectable: Self = Self("Windows.Win32.System.WinRT", "IInspectable"); - pub const IRestrictedErrorInfo: Self = Self("Windows.Win32.System.WinRT", "IRestrictedErrorInfo"); + pub const IRestrictedErrorInfo: Self = + Self("Windows.Win32.System.WinRT", "IRestrictedErrorInfo"); pub const IDispatch: Self = Self("Windows.Win32.System.Com", "IDispatch"); pub const VARIANT: Self = Self("Windows.Win32.System.Variant", "VARIANT"); pub const PROPVARIANT: Self = Self("Windows.Win32.System.Com.StructuredStorage", "PROPVARIANT"); pub fn parse(full_name: &'static str) -> Self { - let index = full_name.rfind('.').expect("Expected full name separated with `.`"); + let index = full_name + .rfind('.') + .expect("Expected full name separated with `.`"); Self(&full_name[0..index], &full_name[index + 1..]) } diff --git a/crates/libs/result/rustfmt.toml b/crates/libs/result/rustfmt.toml deleted file mode 100644 index 43d4840c79..0000000000 --- a/crates/libs/result/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -newline_style = "Unix" diff --git a/rustfmt.toml b/crates/libs/sys/rustfmt.toml similarity index 100% rename from rustfmt.toml rename to crates/libs/sys/rustfmt.toml diff --git a/crates/libs/version/rustfmt.toml b/crates/libs/version/rustfmt.toml deleted file mode 100644 index 43d4840c79..0000000000 --- a/crates/libs/version/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -newline_style = "Unix" diff --git a/crates/libs/registry/rustfmt.toml b/crates/libs/windows/rustfmt.toml similarity index 58% rename from crates/libs/registry/rustfmt.toml rename to crates/libs/windows/rustfmt.toml index 43d4840c79..0bc68903df 100644 --- a/crates/libs/registry/rustfmt.toml +++ b/crates/libs/windows/rustfmt.toml @@ -1 +1,2 @@ newline_style = "Unix" +max_width = 800 diff --git a/crates/samples/components/json_validator_winrt_client_cpp/Cargo.toml b/crates/samples/components/json_validator_winrt_client_cpp/Cargo.toml new file mode 100644 index 0000000000..6e5dbd2125 --- /dev/null +++ b/crates/samples/components/json_validator_winrt_client_cpp/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "sample_component_json_validator_winrt_client_cpp" +version = "0.0.0" +edition = "2021" +publish = false + +[build-dependencies] +cc = "1.0" + +[build-dependencies.cppwinrt] +path = "../../../../crates/libs/cppwinrt" + +[dependencies.windows-targets] +path = "../../../../crates/libs/targets" + +# TODO: this causes a warning about lack of linkage target. The point is to ensure that this binary dependency is built first but +# Cargo doesn't respect cdylib targets. https://github.com/rust-lang/cargo/issues/7825 +[dependencies.sample_component_json_validator_winrt] +path = "../json_validator_winrt" diff --git a/crates/samples/components/json_validator_winrt_client_cpp/build.rs b/crates/samples/components/json_validator_winrt_client_cpp/build.rs new file mode 100644 index 0000000000..6293927b07 --- /dev/null +++ b/crates/samples/components/json_validator_winrt_client_cpp/build.rs @@ -0,0 +1,24 @@ +fn main() { + if !cfg!(target_env = "msvc") { + return; + } + + println!("cargo:rerun-if-changed=src/client.cpp"); + println!("cargo:rustc-link-lib=windows.0.52.0"); + + cppwinrt::cppwinrt([ + "-in", + "../json_validator_winrt/sample.winmd", + &format!("{}\\System32\\WinMetadata", env!("windir")), + "-out", + "src", + ]) + .unwrap(); + + cc::Build::new() + .cpp(true) + .std("c++20") + .flag("/EHsc") + .file("src/client.cpp") + .compile("client"); +} diff --git a/crates/samples/components/json_validator_winrt_client_cpp/src/client.cpp b/crates/samples/components/json_validator_winrt_client_cpp/src/client.cpp new file mode 100644 index 0000000000..f59de0d652 --- /dev/null +++ b/crates/samples/components/json_validator_winrt_client_cpp/src/client.cpp @@ -0,0 +1,34 @@ +#include "winrt/Sample.h" + +using namespace winrt::Sample; + +extern "C" { + void __stdcall client() noexcept { + auto schema = LR"( +{ + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer" + } + } +} + )"; + + auto value = LR"( +{ + "name": "Kenny", + "age": 21 +} + )"; + + // Create a validator with the given schema. + auto validator = JsonValidator(schema); + + // Validate and check the sanitized return value. + auto sanitized = validator.Validate(value); + assert(sanitized == LR"({"age":21,"name":"Kenny"})"); + } +} diff --git a/crates/samples/components/json_validator_winrt_client_cpp/src/lib.rs b/crates/samples/components/json_validator_winrt_client_cpp/src/lib.rs new file mode 100644 index 0000000000..6f1497b02a --- /dev/null +++ b/crates/samples/components/json_validator_winrt_client_cpp/src/lib.rs @@ -0,0 +1,11 @@ +#![cfg(target_env = "msvc")] + +#[test] +fn test() { + extern "system" { + fn client(); + } + unsafe { + client(); + } +} diff --git a/crates/samples/rustfmt.toml b/crates/samples/rustfmt.toml deleted file mode 100644 index 43d4840c79..0000000000 --- a/crates/samples/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -newline_style = "Unix" diff --git a/crates/targets/aarch64_gnullvm/build.rs b/crates/targets/aarch64_gnullvm/build.rs index b5caa2baad..bff093245f 100644 --- a/crates/targets/aarch64_gnullvm/build.rs +++ b/crates/targets/aarch64_gnullvm/build.rs @@ -1,5 +1,8 @@ fn main() { let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); + println!( + "cargo:rustc-link-search=native={}", + std::path::Path::new(&dir).join("lib").display() + ); } diff --git a/crates/targets/aarch64_msvc/build.rs b/crates/targets/aarch64_msvc/build.rs index b5caa2baad..bff093245f 100644 --- a/crates/targets/aarch64_msvc/build.rs +++ b/crates/targets/aarch64_msvc/build.rs @@ -1,5 +1,8 @@ fn main() { let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); + println!( + "cargo:rustc-link-search=native={}", + std::path::Path::new(&dir).join("lib").display() + ); } diff --git a/crates/targets/i686_gnu/build.rs b/crates/targets/i686_gnu/build.rs index b5caa2baad..bff093245f 100644 --- a/crates/targets/i686_gnu/build.rs +++ b/crates/targets/i686_gnu/build.rs @@ -1,5 +1,8 @@ fn main() { let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); + println!( + "cargo:rustc-link-search=native={}", + std::path::Path::new(&dir).join("lib").display() + ); } diff --git a/crates/targets/i686_gnullvm/build.rs b/crates/targets/i686_gnullvm/build.rs index b5caa2baad..bff093245f 100644 --- a/crates/targets/i686_gnullvm/build.rs +++ b/crates/targets/i686_gnullvm/build.rs @@ -1,5 +1,8 @@ fn main() { let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); + println!( + "cargo:rustc-link-search=native={}", + std::path::Path::new(&dir).join("lib").display() + ); } diff --git a/crates/targets/i686_msvc/build.rs b/crates/targets/i686_msvc/build.rs index b5caa2baad..bff093245f 100644 --- a/crates/targets/i686_msvc/build.rs +++ b/crates/targets/i686_msvc/build.rs @@ -1,5 +1,8 @@ fn main() { let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); + println!( + "cargo:rustc-link-search=native={}", + std::path::Path::new(&dir).join("lib").display() + ); } diff --git a/crates/targets/x86_64_gnu/build.rs b/crates/targets/x86_64_gnu/build.rs index b5caa2baad..bff093245f 100644 --- a/crates/targets/x86_64_gnu/build.rs +++ b/crates/targets/x86_64_gnu/build.rs @@ -1,5 +1,8 @@ fn main() { let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); + println!( + "cargo:rustc-link-search=native={}", + std::path::Path::new(&dir).join("lib").display() + ); } diff --git a/crates/targets/x86_64_gnullvm/build.rs b/crates/targets/x86_64_gnullvm/build.rs index b5caa2baad..bff093245f 100644 --- a/crates/targets/x86_64_gnullvm/build.rs +++ b/crates/targets/x86_64_gnullvm/build.rs @@ -1,5 +1,8 @@ fn main() { let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); + println!( + "cargo:rustc-link-search=native={}", + std::path::Path::new(&dir).join("lib").display() + ); } diff --git a/crates/targets/x86_64_msvc/build.rs b/crates/targets/x86_64_msvc/build.rs index b5caa2baad..bff093245f 100644 --- a/crates/targets/x86_64_msvc/build.rs +++ b/crates/targets/x86_64_msvc/build.rs @@ -1,5 +1,8 @@ fn main() { let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); + println!( + "cargo:rustc-link-search=native={}", + std::path::Path::new(&dir).join("lib").display() + ); } diff --git a/crates/tests/agile_reference/tests/tests.rs b/crates/tests/agile_reference/tests/tests.rs index 0afa0f6b38..249fc397fe 100644 --- a/crates/tests/agile_reference/tests/tests.rs +++ b/crates/tests/agile_reference/tests/tests.rs @@ -20,6 +20,6 @@ fn agile_debug() -> Result<()> { assert!(format!("{uri:?}").starts_with("Uri(IUnknown(0x")); let reference = AgileReference::new(&uri)?; - assert!(format!("{reference:?}").starts_with("AgileReference(IAgileReference(IUnknown(0x")); + assert!(format!("{reference:?}").starts_with("AgileReference(IAgileReference(0x")); Ok(()) } diff --git a/crates/tests/implement_core/src/com_chain.rs b/crates/tests/implement_core/src/com_chain.rs new file mode 100644 index 0000000000..5124b390e4 --- /dev/null +++ b/crates/tests/implement_core/src/com_chain.rs @@ -0,0 +1,50 @@ +use windows_core::*; + +#[interface("cccccccc-0000-0000-0000-000000000001")] +unsafe trait IFoo: IUnknown {} + +#[interface("cccccccc-0000-0000-0000-000000000002")] +unsafe trait IFoo2: IFoo {} + +#[interface("cccccccc-0000-0000-0000-000000000003")] +unsafe trait IFoo3: IFoo2 {} + +// ObjectA implements a single interface chain, which consists of 3 different +// interfaces: IFoo3, IFoo2, and IFoo. You do not need to explicitly list all +// of the interfaces in the interface chain. Listing all of the interfaces is +// less efficient because it generates redundant interface chains (pointer +// fields in the the generated ObjectA_Impl type), which will never be used. +#[implement(IFoo3)] +struct ObjectWithChains {} + +impl IFoo_Impl for ObjectWithChains {} +impl IFoo2_Impl for ObjectWithChains {} +impl IFoo3_Impl for ObjectWithChains {} + +#[test] +fn interface_chain_query() { + let object = ComObject::new(ObjectWithChains {}); + let unknown: IUnknown = object.to_interface(); + let _foo: IFoo = unknown.cast().expect("QueryInterface for IFoo"); + let _foo2: IFoo2 = unknown.cast().expect("QueryInterface for IFoo2"); + let _foo3: IFoo3 = unknown.cast().expect("QueryInterface for IFoo3"); +} + +// ObjectRedundantChains implements the same interfaces as ObjectWithChains, +// but it defines more than one interface chain. This is unnecessary because it +// is redundant, but we are verifying that this works. +#[implement(IFoo3, IFoo2, IFoo)] +struct ObjectRedundantChains {} + +impl IFoo_Impl for ObjectRedundantChains {} +impl IFoo2_Impl for ObjectRedundantChains {} +impl IFoo3_Impl for ObjectRedundantChains {} + +#[test] +fn redundant_interface_chains() { + let object = ComObject::new(ObjectRedundantChains {}); + let unknown: IUnknown = object.to_interface(); + let _foo: IFoo = unknown.cast().expect("QueryInterface for IFoo"); + let _foo2: IFoo2 = unknown.cast().expect("QueryInterface for IFoo2"); + let _foo3: IFoo3 = unknown.cast().expect("QueryInterface for IFoo3"); +} diff --git a/crates/tests/implement_core/src/com_object.rs b/crates/tests/implement_core/src/com_object.rs index a5d0eb2be9..6cf227be89 100644 --- a/crates/tests/implement_core/src/com_object.rs +++ b/crates/tests/implement_core/src/com_object.rs @@ -4,7 +4,7 @@ use std::borrow::Borrow; use std::sync::atomic::{AtomicBool, Ordering::SeqCst}; use std::sync::Arc; use windows_core::{ - implement, interface, ComObject, IUnknown, IUnknownImpl, IUnknown_Vtbl, InterfaceRef, + implement, interface, ComObject, IUnknown, IUnknownImpl, IUnknown_Vtbl, Interface, InterfaceRef, }; #[interface("818f2fd1-d479-4398-b286-a93c4c7904d1")] @@ -12,15 +12,28 @@ unsafe trait IFoo: IUnknown { fn get_x(&self) -> u32; fn get_self_as_bar(&self) -> IBar; + + fn common(&self) -> u32; } #[interface("687eb4b2-6df6-41a3-86c7-4b04b94ad2d8")] unsafe trait IBar: IUnknown { fn say_hello(&self); + + fn common(&self) -> u64; +} + +#[interface("4351c285-97ad-450a-b445-8795632d2fb9")] +unsafe trait IBar2: IBar { + fn common(&self) -> f32; } -#[implement(IFoo, IBar)] +const APP_SIGNATURE: [u8; 8] = *b"cafef00d"; + +#[implement(IFoo, IBar, IBar2)] struct MyApp { + // We use signature to verify field offsets for dynamic casts + signature: [u8; 8], x: u32, tombstone: Arc, } @@ -34,12 +47,26 @@ impl IFoo_Impl for MyApp { let outer = MyApp_Impl::from_inner_ref(self); outer.to_interface() } + + unsafe fn common(&self) -> u32 { + 100 + } } impl IBar_Impl for MyApp { unsafe fn say_hello(&self) { println!("Hello!"); } + + unsafe fn common(&self) -> u64 { + 1_000_000_000_000 + } +} + +impl IBar2_Impl for MyApp { + unsafe fn common(&self) -> f32 { + std::f32::consts::PI + } } impl Borrow for MyApp { @@ -63,6 +90,7 @@ impl core::fmt::Display for MyApp { impl Default for MyApp { fn default() -> Self { Self { + signature: APP_SIGNATURE, x: 0, tombstone: Arc::new(Tombstone::default()), } @@ -109,6 +137,7 @@ impl MyApp { fn new(x: u32) -> ComObject { ComObject::new(Self { x, + signature: APP_SIGNATURE, tombstone: Arc::new(Tombstone::default()), }) } @@ -333,6 +362,69 @@ fn from_inner_ref() { unsafe { ibar.say_hello() }; } +#[test] +fn to_object() { + let app = MyApp::new(42); + let tombstone = app.tombstone.clone(); + let app_outer: &MyApp_Impl = &app; + + let second_app = app_outer.to_object(); + assert!(!tombstone.is_dead()); + assert_eq!(second_app.signature, APP_SIGNATURE); + + println!("x = {}", unsafe { second_app.get_x() }); + + drop(second_app); + assert!(!tombstone.is_dead()); + + drop(app); + assert!(tombstone.is_dead()); +} + +#[test] +fn dynamic_cast() { + let app = MyApp::new(42); + let unknown = app.to_interface::(); + + assert!(!unknown.is_object::()); + assert!(unknown.is_object::()); + + let dyn_app_ref: &MyApp_Impl = unknown.cast_object_ref::().unwrap(); + assert_eq!(dyn_app_ref.signature, APP_SIGNATURE); + + let dyn_app_owned: ComObject = unknown.cast_object().unwrap(); + assert_eq!(dyn_app_owned.signature, APP_SIGNATURE); + + let dyn_app_owned_2: ComObject = ComObject::cast_from(&unknown).unwrap(); + assert_eq!(dyn_app_owned_2.signature, APP_SIGNATURE); +} + +// Test that we can invoke the correct method in situations where two different +// interfaces declare a method with the same name, including situations where +// one of the interfaces inherits from the other. +#[test] +fn common_method_name() { + let app = MyApp::new(42); + + let ifoo: IFoo = app.to_interface(); + assert_eq!(unsafe { ifoo.common() }, 100); + + let ibar: IBar = app.to_interface(); + assert_eq!(unsafe { ibar.common() }, 1_000_000_000_000); + + let ibar2: IBar2 = app.to_interface(); + assert_eq!(unsafe { ibar2.common() }, std::f32::consts::PI); +} + +#[test] +fn debug_fmt() { + let app = MyApp::new(42); + let iunknown: IUnknown = app.to_interface(); + println!("IUnknown = {iunknown:?}"); + let ifoo: IFoo = app.to_interface(); + println!("IFoo = {ifoo:?}"); +} + // This tests that we can place a type that is not Send in a ComObject. // Compilation is sufficient to test. #[implement(IBar)] @@ -344,6 +436,10 @@ impl IBar_Impl for UnsendableThing { unsafe fn say_hello(&self) { println!("{}", self.cell.get()); } + + unsafe fn common(&self) -> u64 { + 0 + } } static_assertions::assert_not_impl_all!(UnsendableThing: Send, Sync); @@ -358,6 +454,10 @@ impl IBar_Impl for SendableThing { unsafe fn say_hello(&self) { println!("{}", *self.arc); } + + unsafe fn common(&self) -> u64 { + 0 + } } static_assertions::assert_impl_all!(SendableThing: Send, Sync); diff --git a/crates/tests/implement_core/src/lib.rs b/crates/tests/implement_core/src/lib.rs index e083fca649..aa8f3bec53 100644 --- a/crates/tests/implement_core/src/lib.rs +++ b/crates/tests/implement_core/src/lib.rs @@ -3,4 +3,5 @@ #![cfg(test)] +mod com_chain; mod com_object; diff --git a/crates/tests/readme/Cargo.toml b/crates/tests/readme/Cargo.toml index 1ead2a6a89..2e6dc52009 100644 --- a/crates/tests/readme/Cargo.toml +++ b/crates/tests/readme/Cargo.toml @@ -37,3 +37,6 @@ path = "../../libs/registry" [dev-dependencies.windows-version] path = "../../libs/version" + +[dev-dependencies.cppwinrt] +path = "../../libs/cppwinrt" diff --git a/crates/tests/readme/src/lib.rs b/crates/tests/readme/src/lib.rs index e1d6bf36a6..6a1bd9cb79 100644 --- a/crates/tests/readme/src/lib.rs +++ b/crates/tests/readme/src/lib.rs @@ -6,3 +6,4 @@ #![doc = include_str!("../../../../crates/libs/targets/readme.md")] #![doc = include_str!("../../../../crates/libs/version/readme.md")] #![doc = include_str!("../../../../crates/libs/windows/readme.md")] +#![doc = include_str!("../../../../crates/libs/cppwinrt/readme.md")] diff --git a/crates/tests/rustfmt.toml b/crates/tests/rustfmt.toml deleted file mode 100644 index 43d4840c79..0000000000 --- a/crates/tests/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -newline_style = "Unix" diff --git a/crates/tools/rustfmt.toml b/crates/tools/rustfmt.toml deleted file mode 100644 index 43d4840c79..0000000000 --- a/crates/tools/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -newline_style = "Unix" diff --git a/crates/tools/sys/bindings.txt b/crates/tools/sys/bindings.txt index 56db292a40..7f6a6b5dfa 100644 --- a/crates/tools/sys/bindings.txt +++ b/crates/tools/sys/bindings.txt @@ -1,6 +1,7 @@ --in crates/libs/bindgen/default --out crates/libs/sys/src/lib.rs --config package sys no-bindgen-comment +--config rustfmt-config=max_width=800,newline_style=Unix --filter Windows.Wdk diff --git a/crates/tools/windows/bindings.txt b/crates/tools/windows/bindings.txt index c998ffab1b..3cd700917c 100644 --- a/crates/tools/windows/bindings.txt +++ b/crates/tools/windows/bindings.txt @@ -5,6 +5,7 @@ --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] +--config rustfmt-config=max_width=800,newline_style=Unix --filter Windows diff --git a/crates/tools/yml/src/main.rs b/crates/tools/yml/src/main.rs index 5d31d0b624..c60e79865c 100644 --- a/crates/tools/yml/src/main.rs +++ b/crates/tools/yml/src/main.rs @@ -22,7 +22,7 @@ env: jobs: check: - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: @@ -119,7 +119,7 @@ env: jobs: check: - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: @@ -171,7 +171,7 @@ env: jobs: check: - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: