diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index bc78799931..c415c83416 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -67,6 +67,7 @@ jobs: cargo clippy -p test_alternate_success_code && cargo clippy -p test_arch && cargo clippy -p test_arch_feature && + cargo clippy -p test_array && cargo clippy -p test_bcrypt && cargo clippy -p test_bstr && cargo clippy -p test_calling_convention && diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index baebe3fff8..ad77cf2b44 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -117,6 +117,7 @@ jobs: cargo test --target ${{ matrix.target }} -p test_alternate_success_code && cargo test --target ${{ matrix.target }} -p test_arch && cargo test --target ${{ matrix.target }} -p test_arch_feature && + cargo test --target ${{ matrix.target }} -p test_array && cargo test --target ${{ matrix.target }} -p test_bcrypt && cargo test --target ${{ matrix.target }} -p test_bstr && cargo test --target ${{ matrix.target }} -p test_calling_convention && diff --git a/crates/libs/windows/src/core/array.rs b/crates/libs/windows/src/core/array.rs index 75536fb372..d6b8a171ad 100644 --- a/crates/libs/windows/src/core/array.rs +++ b/crates/libs/windows/src/core/array.rs @@ -54,6 +54,18 @@ impl> Array { array } + /// Creates an array from a pointer and length. The `len` argument is the number of elements, not the number of bytes. + /// # Safety + /// The `data` argument must have been allocated with `CoTaskMemAlloc`. + pub unsafe fn from_raw_parts(data: *mut T::Default, len: u32) -> Self { + Self { data, len } + } + + /// Returns a slice containing the entire array. + pub fn as_slice(&self) -> &[T::Default] { + self + } + /// Returns `true` if the array is empty. pub fn is_empty(&self) -> bool { self.len == 0 diff --git a/crates/tests/array/Cargo.toml b/crates/tests/array/Cargo.toml new file mode 100644 index 0000000000..666fc0e630 --- /dev/null +++ b/crates/tests/array/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "test_array" +version = "0.0.0" +authors = ["Microsoft"] +edition = "2018" + +[dependencies.windows] +path = "../../libs/windows" +features = [ + "Foundation", + "Win32_Media_MediaFoundation", +] diff --git a/crates/tests/array/src/lib.rs b/crates/tests/array/src/lib.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/crates/tests/array/src/lib.rs @@ -0,0 +1 @@ + diff --git a/crates/tests/array/tests/com.rs b/crates/tests/array/tests/com.rs new file mode 100644 index 0000000000..d000cb4744 --- /dev/null +++ b/crates/tests/array/tests/com.rs @@ -0,0 +1,19 @@ +use windows::{core::*, Win32::Media::MediaFoundation::*}; + +#[test] +fn test() -> Result<()> { + unsafe { + let mut data = std::ptr::null_mut(); + let mut len = 0; + + MFTEnumEx(MFT_CATEGORY_VIDEO_ENCODER, MFT_ENUM_FLAG_HARDWARE, None, None, &mut data, &mut len)?; + + let array = Array::::from_raw_parts(data as _, len); + + for i in array.as_slice() { + println!("{}", i.as_ref().unwrap().GetCount()?); + } + + Ok(()) + } +} diff --git a/crates/tests/array/tests/primitive.rs b/crates/tests/array/tests/primitive.rs new file mode 100644 index 0000000000..b78e20ab59 --- /dev/null +++ b/crates/tests/array/tests/primitive.rs @@ -0,0 +1,30 @@ +use windows::core::Array; + +#[test] +fn array() { + let a = Array::::new(); + assert!(a.is_empty()); + + let mut a = Array::::with_len(3); + assert_eq!(a[0], 0); + assert_eq!(a[1], 0); + assert_eq!(a[2], 0); + + a[0] = 1; + a[1] = 2; + a[2] = 3; + + assert_eq!(a[0], 1); + assert_eq!(a[1], 2); + assert_eq!(a[2], 3); + + let result = a.as_slice().iter().fold(0, |acc, x| acc + x); + assert_eq!(result, 6); + + let a = Array::::from_slice(&[4, 5, 6]); + + assert_eq!(a.len(), 3); + assert_eq!(a[0], 4); + assert_eq!(a[1], 5); + assert_eq!(a[2], 6); +} diff --git a/crates/tests/winrt/tests/array.rs b/crates/tests/array/tests/winrt.rs similarity index 74% rename from crates/tests/winrt/tests/array.rs rename to crates/tests/array/tests/winrt.rs index ba2eeb0971..c01abe287c 100644 --- a/crates/tests/winrt/tests/array.rs +++ b/crates/tests/array/tests/winrt.rs @@ -13,8 +13,6 @@ fn array() { a[0] = Uri::CreateUri(&windows::core::HSTRING::from("http://kennykerr.ca")).ok(); a[1] = Uri::CreateUri(&windows::core::HSTRING::from("http://microsoft.com")).ok(); - // TODO: this seems rather tedious... may warrant a windows::Option that's more convenient - // that could handle both nullable and IReference behaviors in a single abstraction. assert!(a[0].as_ref().unwrap().Domain().unwrap() == "kennykerr.ca"); assert!(a[1].as_ref().unwrap().Domain().unwrap() == "microsoft.com"); }