windows_strings/
hstring_builder.rs1use super::*;
2
3pub struct HStringBuilder(*mut HStringHeader);
8
9impl HStringBuilder {
10 pub fn new(len: usize) -> Self {
12 let header = HStringHeader::alloc(len.try_into().unwrap());
13
14 if len > 0 {
15 unsafe { core::ptr::write_bytes((*header).data, 0, len) };
16 }
17
18 Self(header)
19 }
20
21 pub fn trim_end(&mut self) {
23 if let Some(header) = self.as_header_mut() {
24 while header.len > 0
25 && unsafe { header.data.offset(header.len as isize - 1).read() == 0 }
26 {
27 header.len -= 1;
28 }
29
30 if header.len == 0 {
31 unsafe {
32 HStringHeader::free(self.0);
33 }
34 self.0 = core::ptr::null_mut();
35 }
36 }
37 }
38
39 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
41 if let Some(header) = self.as_header() {
42 unsafe {
43 core::slice::from_raw_parts_mut(header.data as *mut _, header.len as usize * 2)
44 }
45 } else {
46 &mut []
47 }
48 }
49
50 fn as_header(&self) -> Option<&HStringHeader> {
51 unsafe { self.0.as_ref() }
52 }
53
54 fn as_header_mut(&mut self) -> Option<&mut HStringHeader> {
55 unsafe { self.0.as_mut() }
56 }
57}
58
59impl From<HStringBuilder> for HSTRING {
60 fn from(value: HStringBuilder) -> Self {
61 if let Some(header) = value.as_header() {
62 unsafe { header.data.offset(header.len as isize).write(0) };
63 let result = Self(value.0);
64 core::mem::forget(value);
65 result
66 } else {
67 Self::new()
68 }
69 }
70}
71
72impl core::ops::Deref for HStringBuilder {
73 type Target = [u16];
74
75 fn deref(&self) -> &[u16] {
76 if let Some(header) = self.as_header() {
77 unsafe { core::slice::from_raw_parts(header.data, header.len as usize) }
78 } else {
79 &[]
80 }
81 }
82}
83
84impl core::ops::DerefMut for HStringBuilder {
85 fn deref_mut(&mut self) -> &mut [u16] {
86 if let Some(header) = self.as_header() {
87 unsafe { core::slice::from_raw_parts_mut(header.data, header.len as usize) }
88 } else {
89 &mut []
90 }
91 }
92}
93
94impl Drop for HStringBuilder {
95 fn drop(&mut self) {
96 unsafe {
97 HStringHeader::free(self.0);
98 }
99 }
100}