Skip to content

Commit

Permalink
Simplify Array usage with non-WinRT types (#2362)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Mar 2, 2023
1 parent 23e0800 commit 5f17e3f
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 2 deletions.
1 change: 1 addition & 0 deletions .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand Down
12 changes: 12 additions & 0 deletions crates/libs/windows/src/core/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ impl<T: Type<T>> Array<T> {
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
Expand Down
12 changes: 12 additions & 0 deletions crates/tests/array/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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",
]
1 change: 1 addition & 0 deletions crates/tests/array/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

19 changes: 19 additions & 0 deletions crates/tests/array/tests/com.rs
Original file line number Diff line number Diff line change
@@ -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::<IMFActivate>::from_raw_parts(data as _, len);

for i in array.as_slice() {
println!("{}", i.as_ref().unwrap().GetCount()?);
}

Ok(())
}
}
30 changes: 30 additions & 0 deletions crates/tests/array/tests/primitive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use windows::core::Array;

#[test]
fn array() {
let a = Array::<i32>::new();
assert!(a.is_empty());

let mut a = Array::<i32>::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::<i32>::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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> that's more convenient
// that could handle both nullable and IReference<T> 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");
}

0 comments on commit 5f17e3f

Please sign in to comment.