1use super::*;
2use alloc::vec::Vec;
3use core::ops::Deref;
4
5#[repr(transparent)]
7pub struct BSTR(*const u16);
8
9impl BSTR {
10 pub const fn new() -> Self {
12 Self(core::ptr::null_mut())
13 }
14
15 pub fn from_wide(value: &[u16]) -> Self {
17 if value.is_empty() {
18 return Self::new();
19 }
20
21 let result = unsafe {
22 Self(bindings::SysAllocStringLen(
23 value.as_ptr(),
24 value.len().try_into().unwrap(),
25 ))
26 };
27
28 assert!(!result.is_empty(), "allocation failed");
29
30 result
31 }
32
33 pub fn display(&self) -> impl core::fmt::Display + '_ {
35 Decode(move || core::char::decode_utf16(self.iter().copied()))
36 }
37
38 #[doc(hidden)]
43 pub unsafe fn from_raw(raw: *const u16) -> Self {
44 Self(raw)
45 }
46
47 #[doc(hidden)]
50 pub fn into_raw(self) -> *const u16 {
51 core::mem::ManuallyDrop::new(self).0
52 }
53}
54
55impl Deref for BSTR {
56 type Target = [u16];
57
58 fn deref(&self) -> &[u16] {
59 let len = if self.0.is_null() {
60 0
61 } else {
62 unsafe { bindings::SysStringLen(self.0) as usize }
63 };
64
65 if len > 0 {
66 unsafe { core::slice::from_raw_parts(self.0, len) }
67 } else {
68 const EMPTY: [u16; 1] = [0];
70 &EMPTY[..0]
71 }
72 }
73}
74
75impl Clone for BSTR {
76 fn clone(&self) -> Self {
77 Self::from_wide(self)
78 }
79}
80
81impl From<&str> for BSTR {
82 fn from(value: &str) -> Self {
83 let value: Vec<u16> = value.encode_utf16().collect();
84 Self::from_wide(&value)
85 }
86}
87
88impl From<String> for BSTR {
89 fn from(value: String) -> Self {
90 value.as_str().into()
91 }
92}
93
94impl From<&String> for BSTR {
95 fn from(value: &String) -> Self {
96 value.as_str().into()
97 }
98}
99
100impl TryFrom<&BSTR> for String {
101 type Error = alloc::string::FromUtf16Error;
102
103 fn try_from(value: &BSTR) -> Result<Self, Self::Error> {
104 Self::from_utf16(value)
105 }
106}
107
108impl TryFrom<BSTR> for String {
109 type Error = alloc::string::FromUtf16Error;
110
111 fn try_from(value: BSTR) -> Result<Self, Self::Error> {
112 Self::try_from(&value)
113 }
114}
115
116impl Default for BSTR {
117 fn default() -> Self {
118 Self(core::ptr::null_mut())
119 }
120}
121
122impl core::fmt::Debug for BSTR {
123 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
124 core::write!(f, "{}", self.display())
125 }
126}
127
128impl PartialEq for BSTR {
129 fn eq(&self, other: &Self) -> bool {
130 self.deref() == other.deref()
131 }
132}
133
134impl Eq for BSTR {}
135
136impl PartialEq<BSTR> for &str {
137 fn eq(&self, other: &BSTR) -> bool {
138 other == self
139 }
140}
141
142impl PartialEq<BSTR> for String {
143 fn eq(&self, other: &BSTR) -> bool {
144 other == self
145 }
146}
147
148impl<T: AsRef<str> + ?Sized> PartialEq<T> for BSTR {
149 fn eq(&self, other: &T) -> bool {
150 self.iter().copied().eq(other.as_ref().encode_utf16())
151 }
152}
153
154impl Drop for BSTR {
155 fn drop(&mut self) {
156 if !self.0.is_null() {
157 unsafe { bindings::SysFreeString(self.0) }
158 }
159 }
160}