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