Skip to content

Commit

Permalink
Inline HSTRING::clear into the drop impl (#1752)
Browse files Browse the repository at this point in the history
  • Loading branch information
rylev authored May 11, 2022
1 parent d0c856b commit caecac5
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 28 deletions.
41 changes: 18 additions & 23 deletions crates/libs/windows/src/core/hstring.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::*;

/// A WinRT string ([HSTRING](https://docs.microsoft.com/en-us/windows/win32/winrt/hstring)),
/// A WinRT string ([HSTRING](https://docs.microsoft.com/en-us/windows/win32/winrt/hstring))
/// is reference-counted and immutable.
#[repr(transparent)]
pub struct HSTRING(*mut Header);
Expand Down Expand Up @@ -53,27 +53,6 @@ impl HSTRING {
std::os::windows::ffi::OsStringExt::from_wide(self.as_wide())
}

/// Clear the contents of the string and free the memory if `self` holds the
/// last reference to the string data.
pub fn clear(&mut self) {
if self.is_empty() {
return;
}

unsafe {
// This flag indicates a "fast pass" string created by some languages where the
// header is allocated on the stack. Such strings must never be freed.
let header = self.0;
debug_assert!((*header).flags & REFERENCE_FLAG == 0);

if (*header).count.release() == 0 {
heap_free(self.0 as RawPtr);
}
}

self.0 = core::ptr::null_mut();
}

/// # Safety
/// len must not be less than the number of items in the iterator.
unsafe fn from_wide_iter<I: Iterator<Item = u16>>(iter: I, len: u32) -> Self {
Expand Down Expand Up @@ -128,7 +107,23 @@ impl Clone for HSTRING {

impl Drop for HSTRING {
fn drop(&mut self) {
self.clear();
if self.is_empty() {
return;
}

unsafe {
let header = std::mem::replace(&mut self.0, core::ptr::null_mut());
// This flag indicates a "fast pass" string created by some languages where the
// header is allocated on the stack. "Fast pass" strings can only ever be used
// as non-owned input params and as such `drop` will never be called. This check
// just ensures the Rust translation never accidentally modeled "fast pass" input
// params as owned `HSTRING` types which would be a bug in the translation.
debug_assert!((*header).flags & REFERENCE_FLAG == 0);

if (*header).count.release() == 0 {
heap_free(header as RawPtr);
}
}
}
}

Expand Down
6 changes: 1 addition & 5 deletions crates/tests/core/tests/hstrings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn hstring_works() {
assert!(empty.is_empty());
assert!(empty.is_empty());

let mut hello = HSTRING::from("Hello");
let hello = HSTRING::from("Hello");
assert!(!hello.is_empty());
assert!(hello.len() == 5);

Expand All @@ -16,10 +16,6 @@ fn hstring_works() {
assert!(rust.len() == 5);

let hello2 = hello.clone();
hello.clear();
assert!(hello.is_empty());
hello.clear();
assert!(hello.is_empty());
assert!(!hello2.is_empty());
assert!(hello2.len() == 5);

Expand Down

0 comments on commit caecac5

Please sign in to comment.