Skip to content

Commit

Permalink
Simplify header handling in HSTRING (#1747)
Browse files Browse the repository at this point in the history
* Simplify header handling in HSTRING

* Make sure we copy the terminating null character
  • Loading branch information
rylev authored May 10, 2022
1 parent fe19c78 commit 7efe684
Showing 1 changed file with 10 additions and 13 deletions.
23 changes: 10 additions & 13 deletions crates/libs/windows/src/core/hstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl HSTRING {
let header = self.0;
debug_assert!((*header).flags & REFERENCE_FLAG == 0);

if (*((*header).shared.as_mut_ptr())).count.release() == 0 {
if (*header).count.release() == 0 {
heap_free(self.0 as RawPtr);
}
}
Expand Down Expand Up @@ -402,11 +402,6 @@ struct Header {
_0: u32,
_1: u32,
data: *mut u16,
shared: core::mem::MaybeUninit<Shared>,
}

#[repr(C)]
struct Shared {
count: RefCount,
buffer_start: u16,
}
Expand All @@ -415,30 +410,32 @@ impl Header {
fn alloc(len: u32) -> *mut Header {
debug_assert!(len != 0);
// Allocate enough space for header and two bytes per character.
// The space for the terminating null character is already accounted for inside of `Header`.
let alloc_size = core::mem::size_of::<Header>() + 2 * len as usize;

// TODO: allow this failure to propagate
let header = heap_alloc(alloc_size).expect("Could not successfully allocate for HSTRING") as *mut Header;

// SAFETY: uses `std::ptr::write` (since `header` is unintialized). `Header` is safe to be all zeros.
unsafe {
(*header).flags = 0;
header.write(std::mem::MaybeUninit::<Header>::zeroed().assume_init());
(*header).len = len;
(*header).data = &mut (*(*header).shared.as_mut_ptr()).buffer_start;
(*(*header).shared.as_mut_ptr()).count = RefCount::new(1);
(*header).count = RefCount::new(1);
(*header).data = &mut (*header).buffer_start;
}
header
}

fn duplicate(&mut self) -> *mut Header {
if self.flags & REFERENCE_FLAG == 0 {
// If this is not a "fast pass" string then simply increment the reference count.
unsafe {
(*self.shared.as_ptr()).count.add_ref();
self
}
self.count.add_ref();
self
} else {
// Otherwise, allocate a new string and copy the value into the new string.
let copy = Header::alloc(self.len);
// SAFETY: since we are duplicating the string it is safe to copy all data from self to the initialized `copy`.
// We copy `len + 1` characters since `len` does not account for the terminating null character.
unsafe {
core::ptr::copy_nonoverlapping(self.data, (*copy).data, self.len as usize + 1);
}
Expand Down

0 comments on commit 7efe684

Please sign in to comment.