Skip to content

Commit b353353

Browse files
committed
Use ptr::NonNull for ComPtr and ComArray
Fixes #66
1 parent ec3430e commit b353353

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed

src/comptr.rs

+17-18
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ use w::um::combaseapi::CoTaskMemFree;
1111

1212
/// Smart pointer for Windows Runtime objects. This pointer automatically maintains the
1313
/// reference count of the underlying COM object.
14-
#[repr(C)] #[derive(Debug)]
15-
pub struct ComPtr<T>(*mut T); // TODO: use ptr::NonNull<T> when stabilized (and lang-compat feature is disabled), see https://github.com/rust-lang/rust/issues/27730
14+
#[repr(transparent)]
15+
#[derive(Debug)]
16+
pub struct ComPtr<T>(ptr::NonNull<T>);
1617

1718
impl<T> fmt::Pointer for ComPtr<T> {
1819
#[inline]
@@ -48,7 +49,7 @@ impl<T> ComPtr<T> {
4849
#[inline]
4950
pub unsafe fn wrap(ptr: *mut T) -> ComPtr<T> { // TODO: Add T: ComInterface bound
5051
debug_assert!(!ptr.is_null());
51-
ComPtr(ptr)
52+
ComPtr(ptr::NonNull::new_unchecked(ptr))
5253
}
5354

5455
/// Creates an optional `ComPtr` to wrap a raw pointer that may be null.
@@ -59,20 +60,20 @@ impl<T> ComPtr<T> {
5960
if ptr.is_null() {
6061
None
6162
} else {
62-
Some(ComPtr(ptr))
63+
Some(ComPtr(ptr::NonNull::new_unchecked(ptr)))
6364
}
6465
}
6566

6667
/// Returns the underlying WinRT object as a reference to an `IInspectable` object.
6768
#[inline]
6869
fn as_inspectable(&self) -> &mut IInspectable where T: RtInterface {
69-
unsafe { &mut *(self.0 as *mut IInspectable) }
70+
unsafe { &mut *(self.0.as_ptr() as *mut IInspectable) }
7071
}
7172

7273
/// Returns the underlying WinRT or COM object as a reference to an `IUnknown` object.
7374
#[inline]
7475
fn as_unknown(&self) -> &mut IUnknown {
75-
unsafe { &mut *(self.0 as *mut IUnknown) }
76+
unsafe { &mut *(self.0.as_ptr() as *mut IUnknown) }
7677
}
7778

7879
/// Changes the type of the underlying COM object to a different interface without doing `QueryInterface`.
@@ -116,21 +117,21 @@ impl<T> Deref for ComPtr<T> {
116117

117118
#[inline]
118119
fn deref(&self) -> &T {
119-
unsafe { &*self.0 }
120+
unsafe { self.0.as_ref() }
120121
}
121122
}
122123
impl<T> DerefMut for ComPtr<T> {
123124
#[inline]
124125
fn deref_mut(&mut self) -> &mut T {
125-
unsafe { &mut*self.0 }
126+
unsafe { self.0.as_mut() }
126127
}
127128
}
128129
impl<T> Clone for ComPtr<T> {
129130
#[inline]
130131
fn clone(&self) -> Self {
131132
unsafe {
132133
self.as_unknown().AddRef();
133-
ComPtr::wrap(self.0)
134+
ComPtr::wrap(self.0.as_ptr())
134135
}
135136
}
136137
}
@@ -152,7 +153,7 @@ impl<T> PartialEq<ComPtr<T>> for ComPtr<T> {
152153
/// using `CoTaskMemFree` on drop.
153154
pub struct ComArray<T> where T: ::RtType {
154155
size: u32,
155-
first: *mut T::Abi
156+
first: ptr::NonNull<T::Abi>
156157
}
157158

158159
impl<T> ComArray<T> where T: ::RtType {
@@ -161,7 +162,7 @@ impl<T> ComArray<T> where T: ::RtType {
161162
assert!(!first.is_null());
162163
ComArray {
163164
size: size,
164-
first: first
165+
first: ptr::NonNull::new_unchecked(first)
165166
}
166167
}
167168

@@ -176,13 +177,13 @@ impl<T> Deref for ComArray<T> where T: ::RtType {
176177
type Target = [T::OutNonNull];
177178
#[inline]
178179
fn deref(&self) -> &[T::OutNonNull] {
179-
unsafe { ::std::slice::from_raw_parts(self.first as *mut T::OutNonNull, self.size as usize) }
180+
unsafe { ::std::slice::from_raw_parts(self.first.as_ptr() as *mut T::OutNonNull, self.size as usize) }
180181
}
181182
}
182183
impl<T> DerefMut for ComArray<T> where T: ::RtType {
183184
#[inline]
184185
fn deref_mut(&mut self) -> &mut [T::OutNonNull] {
185-
unsafe { ::std::slice::from_raw_parts_mut(self.first as *mut T::OutNonNull, self.size as usize) }
186+
unsafe { ::std::slice::from_raw_parts_mut(self.first.as_ptr() as *mut T::OutNonNull, self.size as usize) }
186187
}
187188
}
188189

@@ -191,7 +192,7 @@ impl<T> Drop for ComArray<T> where T: ::RtType {
191192
fn drop(&mut self) {
192193
unsafe {
193194
::std::ptr::drop_in_place(&mut self[..]);
194-
CoTaskMemFree(self.first as LPVOID)
195+
CoTaskMemFree(self.first.as_ptr() as LPVOID)
195196
};
196197
}
197198
}
@@ -216,8 +217,6 @@ mod tests {
216217

217218
// make sure that ComPtr is pointer-sized
218219
assert_eq!(size_of::<::ComPtr<::IInspectable>>(), size_of::<*mut ::IInspectable>());
219-
220-
// TODO: enable this once the null-pointer optimization can be used for Option<ComPtr>
221-
//assert_eq!(size_of::<Option<::ComPtr<::IInspectable>>>(), size_of::<*mut ::IInspectable>());
220+
assert_eq!(size_of::<Option<::ComPtr<::IInspectable>>>(), size_of::<*mut ::IInspectable>());
222221
}
223-
}
222+
}

0 commit comments

Comments
 (0)