1use crate::*;
2use crate::um::stringapiset::{wide_char_to_multi_byte, CodePage, WCFlags, multi_byte_to_wide_char, MBFlags};
3use std::cmp::Ordering;
4use std::ops;
5use std::string::FromUtf16Error;
6use winapi::ctypes::wchar_t;
7
8#[cfg(not(feature = "ansi"))]
9pub type TString = WString;
10
11#[cfg(not(feature = "ansi"))]
12pub type TStr = WStr;
13
14#[cfg(feature = "ansi")]
15pub type TString = AString;
16
17#[cfg(feature = "ansi")]
18pub type TStr = AString;
19
20#[allow(non_snake_case)]
21extern "C" {
22 pub fn wcslen(s: *const wchar_t) -> usize;
23
24 pub fn strlen(s: *const u8) -> usize;
25
26 pub fn wcsnlen(s: *const wchar_t, len: usize) -> usize;
27
28 pub fn strnlen(s: *const u8, len: usize) -> usize;
29}
30
31fn wide_char_to_multi_byte_wrap(
32 code_page: CodePage,
33 wc_flags: WCFlags,
34 x: &[u16],
35) -> OsResult<Vec<u8>> {
36 let l = wide_char_to_multi_byte(
38 code_page,
39 wc_flags,
40 x,
41 &mut [],
42 None,
43 None,
44 )?;
45 let mut ret: Vec<u8> = Vec::with_capacity(l);
46 unsafe {
47 ret.set_len(l);
48
49 let l2 = wide_char_to_multi_byte(
50 code_page,
51 wc_flags,
52 x,
53 ret.as_mut_slice(),
54 None,
55 None,
56 )?;
57 assert_eq!(l, l2);
58 }
59 Ok(ret)
60}
61
62fn multi_byte_to_wide_char_wrap(
63 code_page: CodePage,
64 mb_flags: MBFlags,
65 x: &[u8],
66) -> OsResult<Vec<u16>> {
67 let l = multi_byte_to_wide_char(
68 code_page,
69 mb_flags,
70 x,
71 &mut [],
72 )?;
73 let mut ret: Vec<u16> = Vec::with_capacity(l);
74 unsafe {
75 ret.set_len(l);
76
77 let l2 = multi_byte_to_wide_char(
78 code_page,
79 mb_flags,
80 x,
81 ret.as_mut_slice(),
82 )?;
83 assert_eq!(l, l2);
84 }
85 Ok(ret)
86}
87
88#[repr(C)]
89#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Hash)]
90pub struct WString {
91 inner: Box<[wchar_t]>,
92}
93
94impl WString {
95 #[inline]
96 pub fn as_bytes_with_nul(&self) -> &[u16] { &self.inner }
97
98 #[inline]
99 pub fn as_bytes(&self) -> &[u16] { &self.as_bytes_with_nul()[..self.inner.len() - 1] }
100
101 #[inline]
102 pub fn as_u8_bytes_with_nul(&self) -> &[u8] {
103 unsafe { std::slice::from_raw_parts(self.inner.as_ptr() as *const u8, self.inner.len() * 2) }
104 }
105
106 #[inline]
107 pub fn as_u8_bytes(&self) -> &[u8] { &self.as_u8_bytes_with_nul()[..self.inner.len() - 2] }
108
109 #[inline]
110 pub fn as_c_str(&self) -> &WStr { &*self }
111
112 #[inline]
113 pub fn as_ptr(&self) -> *const u16 { self.inner.as_ptr() }
114
115 #[inline]
116 pub fn len(&self) -> usize { self.inner.len() }
117
118 pub fn to_string(&self) -> Result<String, FromUtf16Error> {
119 String::from_utf16(self.as_bytes())
120 }
121
122 pub fn to_string_lossy(&self) -> String { String::from_utf16_lossy(self.as_bytes()) }
123
124 #[inline]
125 pub fn new<T: Into<Vec<u16>>>(v: T) -> Self { Self::_new(v.into()) }
126
127 #[inline]
128 pub fn new_c<T: Into<Vec<u8>>>(v: T) -> Self { Self::_new2(v.into()) }
129
130 #[inline]
131 fn _new(mut v: Vec<u16>) -> Self {
132 unsafe {
133 let len = wcsnlen(v.as_ptr(), v.len());
134 if len == v.len() {
135 v.reserve_exact(1);
137 v.push(0);
138 }
139 v.set_len(len + 1);
140 Self::new_nul_unchecked(v)
141 }
142 }
143
144 fn from_astr(x: &AStr) -> OsResult<Self> {
145 let wc = multi_byte_to_wide_char_wrap(
146 CodePage::ACP,
147 MBFlags::PRECOMPOSED | MBFlags::ERR_INVALID_CHARS,
148 x.to_bytes_with_nul(),
149 )?;
150 Ok(Self::_new(wc))
151 }
152
153 fn from_astr_lossy(x: &AStr) -> Self {
154 let wc = multi_byte_to_wide_char_wrap(
155 CodePage::ACP,
156 MBFlags::PRECOMPOSED,
157 x.to_bytes_with_nul(),
158 ).unwrap();
159 Self::_new(wc)
160 }
161
162 #[inline]
163 fn _new2(mut v: Vec<u8>) -> Self {
164 if v.len() & 1 == 1 { v.push(0); } unsafe {
166 let v = v.leak();
167 let x = Vec::from_raw_parts(v.as_ptr() as *mut u16, v.len() / 2, v.len() / 2);
168 Self::_new(x)
169 }
170 }
171
172 pub unsafe fn new_nul_unchecked(v: Vec<u16>) -> Self {
175 Self { inner: v.into_boxed_slice() }
176 }
177
178 pub unsafe fn from_raw(ptr: *mut wchar_t) -> Self {
181 let len = wcslen(ptr);
182 let slice = std::slice::from_raw_parts_mut(ptr, len as usize + 1);
183 Self { inner: Box::from_raw(slice) }
184 }
185
186 pub unsafe fn from_raw_s(ptr: *mut u16, len: usize) -> Self {
187 let v = Vec::from_raw_parts(ptr, len, len);
188 Self::_new(v)
189 }
190}
191
192impl ops::Deref for WString {
193 type Target = WStr;
194
195 fn deref(&self) -> &Self::Target {
196 unsafe { WStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
197 }
198}
199
200impl ops::Index<ops::RangeFull> for WString {
201 type Output = WStr;
202
203 #[inline]
204 fn index(&self, _: ops::RangeFull) -> &Self::Output {
205 self
206 }
207}
208
209impl From<&AStr> for WString {
210 fn from(x: &AStr) -> Self {
212 let wc = multi_byte_to_wide_char_wrap(
213 CodePage::ACP,
214 MBFlags::PRECOMPOSED | MBFlags::ERR_INVALID_CHARS,
215 x.to_bytes_with_nul(),
216 ).unwrap();
217 Self::_new(wc)
218 }
219}
220
221impl From<AString> for WString {
222 #[inline]
224 fn from(x: AString) -> Self { Self::from(x.as_c_str()) }
225}
226
227impl From<Vec<u16>> for WString {
228 fn from(x: Vec<u16>) -> Self { Self::_new(x) }
229}
230
231impl From<&str> for WString {
232 fn from(x: &str) -> Self { Self::_new(x.encode_utf16().collect()) }
233}
234
235impl Drop for WString {
236 fn drop(&mut self) {
237 unsafe {
238 *self.inner.as_mut_ptr() = 0;
239 std::mem::forget(self)
240 }
241 }
242}
243
244#[repr(C)]
245#[derive(Debug)]
246pub struct WStr {
247 inner: [wchar_t],
248}
249
250impl WStr {
251 #[inline]
252 pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u16]) -> &Self {
253 &*(bytes as *const [u16] as *const Self)
254 }
255
256 #[inline]
257 pub fn as_ptr(&self) -> *const wchar_t { self.inner.as_ptr() }
258
259 #[inline]
260 pub fn as_mut_ptr(&mut self) -> *mut wchar_t { self.inner.as_mut_ptr() }
261
262 #[inline]
263 pub fn len(&self) -> usize { self.inner.len() }
264
265 #[inline]
266 pub fn to_bytes_with_nul(&self) -> &[u16] { &self.inner }
267
268 pub fn to_bytes(&self) -> &[u16] {
269 let bytes = self.to_bytes_with_nul();
270 &bytes[..bytes.len() - 1]
271 }
272
273 #[inline]
274 pub fn to_u8_bytes_with_nul(&self) -> &[u8] {
275 unsafe { std::slice::from_raw_parts(self.inner.as_ptr() as *const u8, self.inner.len() * 2) }
276 }
277
278 pub fn to_u8_bytes(&self) -> &[u8] {
279 let bytes = self.to_u8_bytes_with_nul();
280 &bytes[..bytes.len() - 2]
281 }
282}
283
284impl PartialEq for WStr {
285 fn eq(&self, other: &Self) -> bool { self.to_bytes().eq(other.to_bytes()) }
286}
287
288impl Eq for WStr {}
289
290impl PartialOrd for WStr {
291 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
292 self.to_bytes().partial_cmp(&other.to_bytes())
293 }
294}
295
296impl Ord for WStr {
297 fn cmp(&self, other: &Self) -> Ordering {
298 self.to_bytes().cmp(&other.to_bytes())
299 }
300}
301
302#[repr(C)]
304#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Hash)]
305pub struct AString {
306 inner: Box<[u8]>,
307}
308
309impl From<&str> for AString {
310 fn from(x: &str) -> Self {
311 let ws = WString::from(x);
313 AString::from(ws)
314 }
315}
316
317impl From<&WStr> for AString {
318 fn from(x: &WStr) -> Self {
319 let mb = wide_char_to_multi_byte_wrap(
320 CodePage::ACP,
321 WCFlags::empty(),
322 x.to_bytes_with_nul(),
323 ).unwrap();
324 Self::_new(mb)
325 }
326}
327
328impl From<WString> for AString {
329 fn from(x: WString) -> Self {
331 Self::from(x.as_c_str())
332 }
333}
334
335impl AString {
336 #[inline]
337 pub fn as_bytes_with_nul(&self) -> &[u8] { &self.inner }
338
339 #[inline]
340 pub fn as_bytes(&self) -> &[u8] { &self.as_bytes_with_nul()[..self.inner.len() - 1] }
341
342 #[inline]
343 pub fn as_c_str(&self) -> &AStr { &*self }
344
345 #[inline]
346 pub fn as_mut_c_str(&mut self) -> &mut AStr { &mut *self }
347
348 #[inline]
349 pub fn as_ptr(&self) -> *const u8 { self.inner.as_ptr() }
350
351 #[inline]
352 pub fn len(&self) -> usize { self.inner.len() }
353
354 pub fn to_string(&self) -> OsResult<String> {
355 let x = WString::from_astr(self.as_c_str())?;
357 unsafe {
358 let mut mb = wide_char_to_multi_byte_wrap(
359 CodePage::UTF8,
360 WCFlags::ERR_INVALID_CHARS,
361 x.as_bytes_with_nul(),
362 )?;
363 mb.set_len(mb.len() - 1); Ok(String::from_utf8_unchecked(mb))
365 }
366 }
367
368 pub fn to_string_lossy(&self) -> String {
369 let x = WString::from_astr_lossy(self.as_c_str());
371 unsafe {
372 let mut mb = wide_char_to_multi_byte_wrap(
373 CodePage::UTF8,
374 WCFlags::empty(),
375 x.as_bytes_with_nul(),
376 ).unwrap();
377 mb.set_len(mb.len() - 1); String::from_utf8_unchecked(mb)
379 }
380 }
381
382 #[inline]
383 pub fn new(v: Vec<u8>) -> Self { Self::_new(v.into()) }
384
385 pub unsafe fn from_str_unchecked(s: &str) -> Self {
402 Self::new(s.as_bytes().to_vec())
403 }
404
405 fn _new(mut v: Vec<u8>) -> Self {
406 unsafe {
407 let len = strnlen(v.as_ptr(), v.len());
408 if len == v.len() {
409 v.reserve_exact(1);
410 v.push(0);
411 }
412 v.set_len(len + 1);
413 Self::new_nul_unchecked(v)
414 }
415 }
416
417 #[inline]
420 pub fn new_nul_unchecked(v: Vec<u8>) -> Self {
421 Self { inner: v.into_boxed_slice() }
422 }
423
424 pub unsafe fn from_raw(ptr: *mut u8) -> Self {
427 let len = strlen(ptr);
428 let slice = std::slice::from_raw_parts_mut(ptr, len as usize + 1);
429 Self { inner: Box::from_raw(slice) }
430 }
431
432 pub unsafe fn from_raw_s(ptr: *mut u8, len: usize) -> Self {
433 let v = Vec::from_raw_parts(ptr, len, len);
434 Self::_new(v)
435 }
436}
437
438impl ops::Deref for AString {
439 type Target = AStr;
440
441 fn deref(&self) -> &Self::Target {
442 unsafe { AStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
443 }
444}
445
446impl ops::DerefMut for AString {
447 fn deref_mut(&mut self) -> &mut Self::Target {
448 unsafe { AStr::from_bytes_with_nul_unchecked_mut(self.as_bytes_with_nul()) }
449 }
450}
451
452impl ops::Index<ops::RangeFull> for AString {
453 type Output = AStr;
454
455 #[inline]
456 fn index(&self, _: ops::RangeFull) -> &Self::Output {
457 self
458 }
459}
460
461impl From<Vec<u8>> for AString {
462 #[inline]
463 fn from(x: Vec<u8>) -> Self { Self::new(x) }
464}
465
466impl Drop for AString {
467 fn drop(&mut self) {
468 unsafe {
469 *self.inner.as_mut_ptr() = 0;
470 std::mem::forget(self)
471 }
472 }
473}
474
475#[repr(C)]
476#[derive(Debug)]
477pub struct AStr {
478 inner: [u8],
479}
480
481impl AStr {
482 #[inline]
483 pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &Self {
484 &*(bytes as *const [u8] as *const Self)
485 }
486
487 #[inline]
488 pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &[u8]) -> &mut Self {
489 &mut *(bytes as *const [u8] as *mut Self)
490 }
491
492 #[inline]
493 pub fn as_ptr(&self) -> *const i8 { self.inner.as_ptr() as *const i8 }
494
495 #[inline]
496 pub fn as_mut_ptr(&mut self) -> *mut i8 { self.inner.as_mut_ptr() as *mut i8 }
497
498 #[inline]
499 pub fn as_u8_ptr(&self) -> *const u8 { self.inner.as_ptr() }
500
501 #[inline]
502 pub fn as_mut_u8_ptr(&mut self) -> *mut u8 { self.inner.as_mut_ptr() }
503
504 #[inline]
505 pub fn len(&self) -> usize { self.inner.len() }
506
507 #[inline]
508 pub fn to_bytes_with_nul(&self) -> &[u8] { &self.inner }
509
510 #[inline]
511 pub fn to_bytes(&self) -> &[u8] {
512 let bytes = self.to_bytes_with_nul();
513 &bytes[..bytes.len() - 1]
514 }
515}
516
517impl PartialEq for AStr {
518 fn eq(&self, other: &Self) -> bool {
519 self.to_bytes().eq(other.to_bytes())
520 }
521}
522
523impl Eq for AStr {}
524
525impl PartialOrd for AStr {
526 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
527 self.to_bytes().partial_cmp(&other.to_bytes())
528 }
529}
530
531impl Ord for AStr {
532 fn cmp(&self, other: &Self) -> Ordering {
533 self.to_bytes().cmp(&other.to_bytes())
534 }
535}