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