widestring/ustring.rs
1//! Owned, growable wide strings with undefined encoding.
2//!
3//! This module contains wide strings and related types.
4
5use crate::{U16CStr, U16CString, U16Str, U32CStr, U32CString, U32Str};
6#[allow(unused_imports)]
7use alloc::{
8 borrow::{Cow, ToOwned},
9 boxed::Box,
10 string::String,
11 vec::Vec,
12};
13#[allow(unused_imports)]
14use core::{
15 borrow::{Borrow, BorrowMut},
16 char, cmp,
17 convert::Infallible,
18 fmt::Write,
19 iter::FromIterator,
20 mem,
21 ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut, RangeBounds},
22 slice::{self, SliceIndex},
23 str::FromStr,
24};
25
26mod iter;
27
28pub use iter::*;
29
30macro_rules! ustring_common_impl {
31 {
32 $(#[$ustring_meta:meta])*
33 struct $ustring:ident([$uchar:ty]);
34 type UStr = $ustr:ident;
35 type UCString = $ucstring:ident;
36 type UCStr = $ucstr:ident;
37 type UtfStr = $utfstr:ident;
38 type UtfString = $utfstring:ident;
39 $(#[$push_meta:meta])*
40 fn push() -> {}
41 $(#[$push_slice_meta:meta])*
42 fn push_slice() -> {}
43 $(#[$into_boxed_ustr_meta:meta])*
44 fn into_boxed_ustr() -> {}
45 } => {
46 $(#[$ustring_meta])*
47 #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
48 #[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
49 pub struct $ustring {
50 pub(crate) inner: Vec<$uchar>,
51 }
52
53 impl $ustring {
54 /// Constructs a new empty wide string.
55 #[inline]
56 #[must_use]
57 pub const fn new() -> Self {
58 Self { inner: Vec::new() }
59 }
60
61 /// Constructs a wide string from a vector.
62 ///
63 /// No checks are made on the contents of the vector. It may or may not be valid
64 /// character data.
65 ///
66 /// # Examples
67 ///
68 /// ```rust
69 /// use widestring::U16String;
70 /// let v = vec![84u16, 104u16, 101u16]; // 'T' 'h' 'e'
71 /// # let cloned = v.clone();
72 /// // Create a wide string from the vector
73 /// let wstr = U16String::from_vec(v);
74 /// # assert_eq!(wstr.into_vec(), cloned);
75 /// ```
76 ///
77 /// ```rust
78 /// use widestring::U32String;
79 /// let v = vec![84u32, 104u32, 101u32]; // 'T' 'h' 'e'
80 /// # let cloned = v.clone();
81 /// // Create a wide string from the vector
82 /// let wstr = U32String::from_vec(v);
83 /// # assert_eq!(wstr.into_vec(), cloned);
84 /// ```
85 #[inline]
86 #[must_use]
87 pub fn from_vec(raw: impl Into<Vec<$uchar>>) -> Self {
88 Self { inner: raw.into() }
89 }
90
91 /// Constructs a wide string copy from a pointer and a length.
92 ///
93 /// The `len` argument is the number of elements, **not** the number of bytes.
94 ///
95 /// # Safety
96 ///
97 /// This function is unsafe as there is no guarantee that the given pointer is valid for
98 /// `len` elements.
99 ///
100 /// In addition, the data must meet the safety conditions of
101 /// [std::slice::from_raw_parts].
102 ///
103 /// # Panics
104 ///
105 /// Panics if `len` is greater than 0 but `p` is a null pointer.
106 #[must_use]
107 pub unsafe fn from_ptr(p: *const $uchar, len: usize) -> Self {
108 if len == 0 {
109 return Self::new();
110 }
111 assert!(!p.is_null());
112 let slice = slice::from_raw_parts(p, len);
113 Self::from_vec(slice)
114 }
115
116 /// Constructs a wide string with the given capacity.
117 ///
118 /// The string will be able to hold exactly `capacity` elements without reallocating.
119 /// If `capacity` is set to 0, the string will not initially allocate.
120 #[inline]
121 #[must_use]
122 pub fn with_capacity(capacity: usize) -> Self {
123 Self {
124 inner: Vec::with_capacity(capacity),
125 }
126 }
127
128 /// Returns the capacity this wide string can hold without reallocating.
129 #[inline]
130 #[must_use]
131 pub fn capacity(&self) -> usize {
132 self.inner.capacity()
133 }
134
135 /// Truncates the wide string to zero length.
136 #[inline]
137 pub fn clear(&mut self) {
138 self.inner.clear()
139 }
140
141 /// Reserves the capacity for at least `additional` more capacity to be inserted in the
142 /// given wide string.
143 ///
144 /// More space may be reserved to avoid frequent allocations.
145 #[inline]
146 pub fn reserve(&mut self, additional: usize) {
147 self.inner.reserve(additional)
148 }
149
150 /// Reserves the minimum capacity for exactly `additional` more capacity to be inserted
151 /// in the given wide string. Does nothing if the capacity is already sufficient.
152 ///
153 /// Note that the allocator may give more space than is requested. Therefore capacity
154 /// can not be relied upon to be precisely minimal. Prefer [`reserve`][Self::reserve] if
155 /// future insertions are expected.
156 #[inline]
157 pub fn reserve_exact(&mut self, additional: usize) {
158 self.inner.reserve_exact(additional)
159 }
160
161 /// Converts the string into a [`Vec`], consuming the string in the process.
162 #[inline]
163 #[must_use]
164 pub fn into_vec(self) -> Vec<$uchar> {
165 self.inner
166 }
167
168 /// Converts to a wide string slice.
169 #[inline]
170 #[must_use]
171 pub fn as_ustr(&self) -> &$ustr {
172 $ustr::from_slice(&self.inner)
173 }
174
175 /// Converts to a mutable wide string slice.
176 #[inline]
177 #[must_use]
178 pub fn as_mut_ustr(&mut self) -> &mut $ustr {
179 $ustr::from_slice_mut(&mut self.inner)
180 }
181
182 /// Returns a [`Vec`] reference to the contents of this string.
183 #[inline]
184 #[must_use]
185 pub fn as_vec(&self) -> &Vec<$uchar> {
186 &self.inner
187 }
188
189 /// Returns a mutable reference to the contents of this string.
190 #[inline]
191 #[must_use]
192 pub fn as_mut_vec(&mut self) -> &mut Vec<$uchar> {
193 &mut self.inner
194 }
195
196 $(#[$push_meta])*
197 #[inline]
198 pub fn push(&mut self, s: impl AsRef<$ustr>) {
199 self.inner.extend_from_slice(&s.as_ref().as_slice())
200 }
201
202 $(#[$push_slice_meta])*
203 #[inline]
204 pub fn push_slice(&mut self, s: impl AsRef<[$uchar]>) {
205 self.inner.extend_from_slice(s.as_ref())
206 }
207
208 /// Shrinks the capacity of the wide string to match its length.
209 #[inline]
210 pub fn shrink_to_fit(&mut self) {
211 self.inner.shrink_to_fit();
212 }
213
214 /// Shrinks the capacity of this string with a lower bound.
215 ///
216 /// The capacity will remain at least as large as both the length and the supplied
217 /// value.
218 ///
219 /// If the current capacity is less than the lower limit, this is a no-op.
220 #[inline]
221 pub fn shrink_to(&mut self, min_capacity: usize) {
222 self.inner.shrink_to(min_capacity)
223 }
224
225 $(#[$into_boxed_ustr_meta])*
226 #[must_use]
227 pub fn into_boxed_ustr(self) -> Box<$ustr> {
228 let rw = Box::into_raw(self.inner.into_boxed_slice()) as *mut $ustr;
229 unsafe { Box::from_raw(rw) }
230 }
231
232 /// Shortens this string to the specified length.
233 ///
234 /// If `new_len` is greater than the string's current length, this has no effect.
235 ///
236 /// Note that this method has no effect on the allocated capacity of the string.
237 #[inline]
238 pub fn truncate(&mut self, new_len: usize) {
239 self.inner.truncate(new_len)
240 }
241
242 /// Inserts a string slice into this string at a specified position.
243 ///
244 /// This is an _O(n)_ operation as it requires copying every element in the buffer.
245 ///
246 /// # Panics
247 ///
248 /// Panics if `idx` is larger than the string's length.
249 pub fn insert_ustr(&mut self, idx: usize, string: &$ustr) {
250 assert!(idx <= self.len());
251 self.inner
252 .resize_with(self.len() + string.len(), Default::default);
253 self.inner.copy_within(idx.., idx + string.len());
254 self.inner[idx..].copy_from_slice(string.as_slice());
255 }
256
257 /// Splits the string into two at the given index.
258 ///
259 /// Returns a newly allocated string. `self` contains values `[0, at)`, and the returned
260 /// string contains values `[at, len)`.
261 ///
262 /// Note that the capacity of `self` does not change.
263 ///
264 /// # Panics
265 ///
266 /// Panics if `at` is equal to or greater than the length of the string.
267 #[inline]
268 #[must_use]
269 pub fn split_off(&mut self, at: usize) -> $ustring {
270 Self::from_vec(self.inner.split_off(at))
271 }
272
273 /// Retains only the elements specified by the predicate.
274 ///
275 /// In other words, remove all elements `e` such that `f(e)` returns `false`. This
276 /// method operates in place, visiting each element exactly once in the original order,
277 /// and preserves the order of the retained elements.
278 pub fn retain<F>(&mut self, mut f: F)
279 where
280 F: FnMut($uchar) -> bool,
281 {
282 self.inner.retain(|e| f(*e))
283 }
284
285 /// Creates a draining iterator that removes the specified range in the string and
286 /// yields the removed elements.
287 ///
288 /// Note: The element range is removed even if the iterator is not consumed until the
289 /// end.
290 ///
291 /// # Panics
292 ///
293 /// Panics if the starting point or end point are out of bounds.
294 pub fn drain<R>(&mut self, range: R) -> Drain<'_, $uchar>
295 where
296 R: RangeBounds<usize>,
297 {
298 Drain { inner: self.inner.drain(range) }
299 }
300
301 /// Removes the specified range in the string, and replaces it with the given string.
302 ///
303 /// The given string doesn't need to be the same length as the range.
304 ///
305 /// # Panics
306 ///
307 /// Panics if the starting point or end point are out of bounds.
308 pub fn replace_range<R>(&mut self, range: R, replace_with: impl AsRef<$ustr>)
309 where
310 R: RangeBounds<usize>,
311 {
312 self.inner
313 .splice(range, replace_with.as_ref().as_slice().iter().copied());
314 }
315 }
316
317 impl Add<&$ustr> for $ustring {
318 type Output = $ustring;
319
320 #[inline]
321 fn add(mut self, rhs: &$ustr) -> Self::Output {
322 self.push(rhs);
323 self
324 }
325 }
326
327 impl Add<&$ucstr> for $ustring {
328 type Output = $ustring;
329
330 #[inline]
331 fn add(mut self, rhs: &$ucstr) -> Self::Output {
332 self.push(rhs);
333 self
334 }
335 }
336
337 impl Add<&crate::$utfstr> for $ustring {
338 type Output = $ustring;
339
340 #[inline]
341 fn add(mut self, rhs: &crate::$utfstr) -> Self::Output {
342 self.push(rhs);
343 self
344 }
345 }
346
347 impl Add<&str> for $ustring {
348 type Output = $ustring;
349
350 #[inline]
351 fn add(mut self, rhs: &str) -> Self::Output {
352 self.push_str(rhs);
353 self
354 }
355 }
356
357 impl AddAssign<&$ustr> for $ustring {
358 #[inline]
359 fn add_assign(&mut self, rhs: &$ustr) {
360 self.push(rhs)
361 }
362 }
363
364 impl AddAssign<&$ucstr> for $ustring {
365 #[inline]
366 fn add_assign(&mut self, rhs: &$ucstr) {
367 self.push(rhs)
368 }
369 }
370
371 impl AddAssign<&crate::$utfstr> for $ustring {
372 #[inline]
373 fn add_assign(&mut self, rhs: &crate::$utfstr) {
374 self.push(rhs)
375 }
376 }
377
378 impl AddAssign<&str> for $ustring {
379 #[inline]
380 fn add_assign(&mut self, rhs: &str) {
381 self.push_str(rhs);
382 }
383 }
384
385 impl AsMut<$ustr> for $ustring {
386 #[inline]
387 fn as_mut(&mut self) -> &mut $ustr {
388 self.as_mut_ustr()
389 }
390 }
391
392 impl AsMut<[$uchar]> for $ustring {
393 #[inline]
394 fn as_mut(&mut self) -> &mut [$uchar] {
395 self.as_mut_slice()
396 }
397 }
398
399 impl AsRef<$ustr> for $ustring {
400 #[inline]
401 fn as_ref(&self) -> &$ustr {
402 self.as_ustr()
403 }
404 }
405
406 impl AsRef<[$uchar]> for $ustring {
407 #[inline]
408 fn as_ref(&self) -> &[$uchar] {
409 self.as_slice()
410 }
411 }
412
413 impl Borrow<$ustr> for $ustring {
414 #[inline]
415 fn borrow(&self) -> &$ustr {
416 self.as_ustr()
417 }
418 }
419
420 impl BorrowMut<$ustr> for $ustring {
421 #[inline]
422 fn borrow_mut(&mut self) -> &mut $ustr {
423 self.as_mut_ustr()
424 }
425 }
426
427 impl Default for Box<$ustr> {
428 #[inline]
429 fn default() -> Self {
430 let boxed: Box<[$uchar]> = Box::from([]);
431 let rw = Box::into_raw(boxed) as *mut $ustr;
432 unsafe { Box::from_raw(rw) }
433 }
434 }
435
436 impl Deref for $ustring {
437 type Target = $ustr;
438
439 #[inline]
440 fn deref(&self) -> &$ustr {
441 self.as_ustr()
442 }
443 }
444
445 impl DerefMut for $ustring {
446 #[inline]
447 fn deref_mut(&mut self) -> &mut Self::Target {
448 self.as_mut_ustr()
449 }
450 }
451
452 impl<'a> Extend<&'a $ustr> for $ustring {
453 #[inline]
454 fn extend<T: IntoIterator<Item = &'a $ustr>>(&mut self, iter: T) {
455 iter.into_iter().for_each(|s| self.push(s))
456 }
457 }
458
459 impl<'a> Extend<&'a $ucstr> for $ustring {
460 #[inline]
461 fn extend<T: IntoIterator<Item = &'a $ucstr>>(&mut self, iter: T) {
462 iter.into_iter().for_each(|s| self.push(s))
463 }
464 }
465
466 impl<'a> Extend<&'a crate::$utfstr> for $ustring {
467 #[inline]
468 fn extend<T: IntoIterator<Item = &'a crate::$utfstr>>(&mut self, iter: T) {
469 iter.into_iter().for_each(|s| self.push(s))
470 }
471 }
472
473 impl<'a> Extend<&'a str> for $ustring {
474 #[inline]
475 fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) {
476 iter.into_iter().for_each(|s| self.push_str(s))
477 }
478 }
479
480 impl Extend<$ustring> for $ustring {
481 #[inline]
482 fn extend<T: IntoIterator<Item = $ustring>>(&mut self, iter: T) {
483 iter.into_iter().for_each(|s| self.push(s))
484 }
485 }
486
487 impl Extend<$ucstring> for $ustring {
488 #[inline]
489 fn extend<T: IntoIterator<Item = $ucstring>>(&mut self, iter: T) {
490 iter.into_iter().for_each(|s| self.push(s.as_ucstr()))
491 }
492 }
493
494 impl Extend<crate::$utfstring> for $ustring {
495 #[inline]
496 fn extend<T: IntoIterator<Item = crate::$utfstring>>(&mut self, iter: T) {
497 iter.into_iter().for_each(|s| self.push(s.as_ustr()))
498 }
499 }
500
501 impl Extend<String> for $ustring {
502 #[inline]
503 fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
504 iter.into_iter().for_each(|s| self.push_str(s))
505 }
506 }
507
508 impl Extend<char> for $ustring {
509 #[inline]
510 fn extend<T: IntoIterator<Item = char>>(&mut self, iter: T) {
511 let iter = iter.into_iter();
512 let (lower_bound, _) = iter.size_hint();
513 self.reserve(lower_bound);
514 iter.for_each(|c| self.push_char(c));
515 }
516 }
517
518 impl<'a> Extend<&'a char> for $ustring {
519 #[inline]
520 fn extend<T: IntoIterator<Item = &'a char>>(&mut self, iter: T) {
521 self.extend(iter.into_iter().copied())
522 }
523 }
524
525 impl Extend<Box<$ustr>> for $ustring {
526 #[inline]
527 fn extend<T: IntoIterator<Item = Box<$ustr>>>(&mut self, iter: T) {
528 iter.into_iter().for_each(|s| self.push(s))
529 }
530 }
531
532 impl<'a> Extend<Cow<'a, $ustr>> for $ustring {
533 #[inline]
534 fn extend<T: IntoIterator<Item = Cow<'a, $ustr>>>(&mut self, iter: T) {
535 iter.into_iter().for_each(|s| self.push(s))
536 }
537 }
538
539 impl From<$ustring> for Vec<$uchar> {
540 #[inline]
541 fn from(value: $ustring) -> Self {
542 value.into_vec()
543 }
544 }
545
546 impl<'a> From<$ustring> for Cow<'a, $ustr> {
547 #[inline]
548 fn from(s: $ustring) -> Self {
549 Cow::Owned(s)
550 }
551 }
552
553 impl From<Vec<$uchar>> for $ustring {
554 #[inline]
555 fn from(value: Vec<$uchar>) -> Self {
556 Self::from_vec(value)
557 }
558 }
559
560 impl From<String> for $ustring {
561 #[inline]
562 fn from(s: String) -> Self {
563 Self::from_str(&s)
564 }
565 }
566
567 impl From<&str> for $ustring {
568 #[inline]
569 fn from(s: &str) -> Self {
570 Self::from_str(s)
571 }
572 }
573
574 #[cfg(feature = "std")]
575 impl From<std::ffi::OsString> for $ustring {
576 #[inline]
577 fn from(s: std::ffi::OsString) -> Self {
578 Self::from_os_str(&s)
579 }
580 }
581
582 #[cfg(feature = "std")]
583 impl From<$ustring> for std::ffi::OsString {
584 #[inline]
585 fn from(s: $ustring) -> Self {
586 s.to_os_string()
587 }
588 }
589
590 impl<'a, T: ?Sized + AsRef<$ustr>> From<&'a T> for $ustring {
591 #[inline]
592 fn from(s: &'a T) -> Self {
593 s.as_ref().to_ustring()
594 }
595 }
596
597 impl<'a> From<&'a $ustr> for Cow<'a, $ustr> {
598 #[inline]
599 fn from(s: &'a $ustr) -> Self {
600 Cow::Borrowed(s)
601 }
602 }
603
604 impl<'a> From<&'a $ustr> for Box<$ustr> {
605 fn from(s: &'a $ustr) -> Self {
606 let boxed: Box<[$uchar]> = Box::from(&s.inner);
607 let rw = Box::into_raw(boxed) as *mut $ustr;
608 unsafe { Box::from_raw(rw) }
609 }
610 }
611
612 impl From<Box<$ustr>> for $ustring {
613 #[inline]
614 fn from(boxed: Box<$ustr>) -> Self {
615 boxed.into_ustring()
616 }
617 }
618
619 impl From<$ustring> for Box<$ustr> {
620 #[inline]
621 fn from(s: $ustring) -> Self {
622 s.into_boxed_ustr()
623 }
624 }
625
626 impl<'a> FromIterator<&'a $ustr> for $ustring {
627 #[inline]
628 fn from_iter<T: IntoIterator<Item = &'a $ustr>>(iter: T) -> Self {
629 let mut string = Self::new();
630 string.extend(iter);
631 string
632 }
633 }
634
635 impl<'a> FromIterator<&'a $ucstr> for $ustring {
636 #[inline]
637 fn from_iter<T: IntoIterator<Item = &'a $ucstr>>(iter: T) -> Self {
638 let mut string = Self::new();
639 string.extend(iter);
640 string
641 }
642 }
643
644 impl<'a> FromIterator<&'a crate::$utfstr> for $ustring {
645 #[inline]
646 fn from_iter<T: IntoIterator<Item = &'a crate::$utfstr>>(iter: T) -> Self {
647 let mut string = Self::new();
648 string.extend(iter);
649 string
650 }
651 }
652
653 impl<'a> FromIterator<&'a str> for $ustring {
654 #[inline]
655 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
656 let mut string = Self::new();
657 string.extend(iter);
658 string
659 }
660 }
661
662 impl FromIterator<$ustring> for $ustring {
663 #[inline]
664 fn from_iter<T: IntoIterator<Item = $ustring>>(iter: T) -> Self {
665 let mut string = Self::new();
666 string.extend(iter);
667 string
668 }
669 }
670
671 impl FromIterator<$ucstring> for $ustring {
672 #[inline]
673 fn from_iter<T: IntoIterator<Item = $ucstring>>(iter: T) -> Self {
674 let mut string = Self::new();
675 string.extend(iter);
676 string
677 }
678 }
679
680 impl FromIterator<crate::$utfstring> for $ustring {
681 #[inline]
682 fn from_iter<T: IntoIterator<Item = crate::$utfstring>>(iter: T) -> Self {
683 let mut string = Self::new();
684 string.extend(iter);
685 string
686 }
687 }
688
689 impl FromIterator<String> for $ustring {
690 #[inline]
691 fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
692 let mut string = Self::new();
693 string.extend(iter);
694 string
695 }
696 }
697
698 impl FromIterator<char> for $ustring {
699 #[inline]
700 fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
701 let mut string = Self::new();
702 string.extend(iter);
703 string
704 }
705 }
706
707 impl<'a> FromIterator<&'a char> for $ustring {
708 #[inline]
709 fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
710 let mut string = Self::new();
711 string.extend(iter);
712 string
713 }
714 }
715
716 impl FromIterator<Box<$ustr>> for $ustring {
717 #[inline]
718 fn from_iter<T: IntoIterator<Item = Box<$ustr>>>(iter: T) -> Self {
719 let mut string = Self::new();
720 string.extend(iter);
721 string
722 }
723 }
724
725 impl<'a> FromIterator<Cow<'a, $ustr>> for $ustring {
726 #[inline]
727 fn from_iter<T: IntoIterator<Item = Cow<'a, $ustr>>>(iter: T) -> Self {
728 let mut string = Self::new();
729 string.extend(iter);
730 string
731 }
732 }
733
734 impl FromStr for $ustring {
735 type Err = Infallible;
736
737 #[inline]
738 fn from_str(s: &str) -> Result<Self, Self::Err> {
739 Ok(Self::from_str(s))
740 }
741 }
742
743 impl<I> Index<I> for $ustring
744 where
745 I: SliceIndex<[$uchar], Output = [$uchar]>,
746 {
747 type Output = $ustr;
748
749 #[inline]
750 fn index(&self, index: I) -> &$ustr {
751 &self.as_ustr()[index]
752 }
753 }
754
755 impl<I> IndexMut<I> for $ustring
756 where
757 I: SliceIndex<[$uchar], Output = [$uchar]>,
758 {
759 fn index_mut(&mut self, index: I) -> &mut Self::Output {
760 &mut self.as_mut_ustr()[index]
761 }
762 }
763
764 impl PartialEq<$ustr> for $ustring {
765 #[inline]
766 fn eq(&self, other: &$ustr) -> bool {
767 self.as_ustr() == other
768 }
769 }
770
771 impl PartialEq<$ucstr> for $ustring {
772 #[inline]
773 fn eq(&self, other: &$ucstr) -> bool {
774 self.as_ustr() == other
775 }
776 }
777
778 impl PartialEq<$ucstring> for $ustring {
779 #[inline]
780 fn eq(&self, other: &$ucstring) -> bool {
781 self.as_ustr() == other.as_ucstr()
782 }
783 }
784
785 impl<'a> PartialEq<&'a $ustr> for $ustring {
786 #[inline]
787 fn eq(&self, other: &&'a $ustr) -> bool {
788 self.as_ustr() == *other
789 }
790 }
791
792 impl<'a> PartialEq<&'a $ucstr> for $ustring {
793 #[inline]
794 fn eq(&self, other: &&'a $ucstr) -> bool {
795 self.as_ustr() == *other
796 }
797 }
798
799 impl<'a> PartialEq<Cow<'a, $ustr>> for $ustring {
800 #[inline]
801 fn eq(&self, other: &Cow<'a, $ustr>) -> bool {
802 self.as_ustr() == other.as_ref()
803 }
804 }
805
806 impl<'a> PartialEq<Cow<'a, $ucstr>> for $ustring {
807 #[inline]
808 fn eq(&self, other: &Cow<'a, $ucstr>) -> bool {
809 self.as_ustr() == other.as_ref()
810 }
811 }
812
813 impl PartialEq<$ustring> for $ustr {
814 #[inline]
815 fn eq(&self, other: &$ustring) -> bool {
816 self == other.as_ustr()
817 }
818 }
819
820 impl PartialEq<$ustring> for $ucstr {
821 #[inline]
822 fn eq(&self, other: &$ustring) -> bool {
823 self.as_ustr() == other.as_ustr()
824 }
825 }
826
827 impl PartialEq<$ustring> for &$ustr {
828 #[inline]
829 fn eq(&self, other: &$ustring) -> bool {
830 self == other.as_ustr()
831 }
832 }
833
834 impl PartialEq<$ustring> for &$ucstr {
835 #[inline]
836 fn eq(&self, other: &$ustring) -> bool {
837 self.as_ustr() == other.as_ustr()
838 }
839 }
840
841 impl PartialOrd<$ustr> for $ustring {
842 #[inline]
843 fn partial_cmp(&self, other: &$ustr) -> Option<cmp::Ordering> {
844 self.as_ustr().partial_cmp(other)
845 }
846 }
847
848 impl PartialOrd<$ucstr> for $ustring {
849 #[inline]
850 fn partial_cmp(&self, other: &$ucstr) -> Option<cmp::Ordering> {
851 self.as_ustr().partial_cmp(other)
852 }
853 }
854
855 impl<'a> PartialOrd<&'a $ustr> for $ustring {
856 #[inline]
857 fn partial_cmp(&self, other: &&'a $ustr) -> Option<cmp::Ordering> {
858 self.as_ustr().partial_cmp(*other)
859 }
860 }
861
862 impl<'a> PartialOrd<&'a $ucstr> for $ustring {
863 #[inline]
864 fn partial_cmp(&self, other: &&'a $ucstr) -> Option<cmp::Ordering> {
865 self.as_ustr().partial_cmp(*other)
866 }
867 }
868
869 impl<'a> PartialOrd<Cow<'a, $ustr>> for $ustring {
870 #[inline]
871 fn partial_cmp(&self, other: &Cow<'a, $ustr>) -> Option<cmp::Ordering> {
872 self.as_ustr().partial_cmp(other.as_ref())
873 }
874 }
875
876 impl<'a> PartialOrd<Cow<'a, $ucstr>> for $ustring {
877 #[inline]
878 fn partial_cmp(&self, other: &Cow<'a, $ucstr>) -> Option<cmp::Ordering> {
879 self.as_ustr().partial_cmp(other.as_ref())
880 }
881 }
882
883 impl PartialOrd<$ucstring> for $ustring {
884 #[inline]
885 fn partial_cmp(&self, other: &$ucstring) -> Option<cmp::Ordering> {
886 self.as_ustr().partial_cmp(other.as_ucstr())
887 }
888 }
889
890 impl ToOwned for $ustr {
891 type Owned = $ustring;
892
893 #[inline]
894 fn to_owned(&self) -> $ustring {
895 self.to_ustring()
896 }
897 }
898
899 impl Write for $ustring {
900 #[inline]
901 fn write_str(&mut self, s: &str) -> core::fmt::Result {
902 self.push_str(s);
903 Ok(())
904 }
905
906 #[inline]
907 fn write_char(&mut self, c: char) -> core::fmt::Result {
908 self.push_char(c);
909 Ok(())
910 }
911 }
912 };
913}
914
915ustring_common_impl! {
916 /// An owned, mutable 16-bit wide string with undefined encoding.
917 ///
918 /// The string slice of a [`U16String`] is [`U16Str`].
919 ///
920 /// [`U16String`] are strings that do not have a defined encoding. While it is sometimes
921 /// assumed that they contain possibly invalid or ill-formed UTF-16 data, they may be used for
922 /// any wide encoded string. This is because [`U16String`] is intended to be used with FFI
923 /// functions, where proper encoding cannot be guaranteed. If you need string slices that are
924 /// always valid UTF-16 strings, use [`Utf16String`][crate::Utf16String] instead.
925 ///
926 /// Because [`U16String`] does not have a defined encoding, no restrictions are placed on
927 /// mutating or indexing the string. This means that even if the string contained properly
928 /// encoded UTF-16 or other encoding data, mutationing or indexing may result in malformed data.
929 /// Convert to a [`Utf16String`][crate::Utf16String] if retaining proper UTF-16 encoding is
930 /// desired.
931 ///
932 /// # FFI considerations
933 ///
934 /// [`U16String`] is not aware of nul values. Strings may or may not be nul-terminated, and may
935 /// contain invalid and ill-formed UTF-16. These strings are intended to be used with FFI functions
936 /// that directly use string length, where the strings are known to have proper nul-termination
937 /// already, or where strings are merely being passed through without modification.
938 ///
939 /// [`U16CString`][crate::U16CString] should be used instead if nul-aware strings are required.
940 ///
941 /// # Examples
942 ///
943 /// The easiest way to use [`U16String`] outside of FFI is with the [`u16str!`][crate::u16str]
944 /// macro to convert string literals into UTF-16 string slices at compile time:
945 ///
946 /// ```
947 /// use widestring::{u16str, U16String};
948 /// let hello = U16String::from(u16str!("Hello, world!"));
949 /// ```
950 ///
951 /// You can also convert any [`u16`] slice or vector directly:
952 ///
953 /// ```
954 /// use widestring::{u16str, U16String};
955 ///
956 /// let sparkle_heart = vec![0xd83d, 0xdc96];
957 /// let sparkle_heart = U16String::from_vec(sparkle_heart);
958 ///
959 /// assert_eq!(u16str!("💖"), sparkle_heart);
960 ///
961 /// // This unpaired UTf-16 surrogate is invalid UTF-16, but is perfectly valid in U16String
962 /// let malformed_utf16 = vec![0x0, 0xd83d]; // Note that nul values are also valid an untouched
963 /// let s = U16String::from_vec(malformed_utf16);
964 ///
965 /// assert_eq!(s.len(), 2);
966 /// ```
967 ///
968 /// The following example constructs a [`U16String`] and shows how to convert a [`U16String`] to
969 /// a regular Rust [`String`].
970 ///
971 /// ```rust
972 /// use widestring::U16String;
973 /// let s = "Test";
974 /// // Create a wide string from the rust string
975 /// let wstr = U16String::from_str(s);
976 /// // Convert back to a rust string
977 /// let rust_str = wstr.to_string_lossy();
978 /// assert_eq!(rust_str, "Test");
979 /// ```
980 struct U16String([u16]);
981
982 type UStr = U16Str;
983 type UCString = U16CString;
984 type UCStr = U16CStr;
985 type UtfStr = Utf16Str;
986 type UtfString = Utf16String;
987
988 /// Extends the string with the given string slice.
989 ///
990 /// No checks are performed on the strings. It is possible to end up nul values inside
991 /// the string, or invalid encoding, and it is up to the caller to determine if that is
992 /// acceptable.
993 ///
994 /// # Examples
995 ///
996 /// ```rust
997 /// use widestring::U16String;
998 /// let s = "MyString";
999 /// let mut wstr = U16String::from_str(s);
1000 /// let cloned = wstr.clone();
1001 /// // Push the clone to the end, repeating the string twice.
1002 /// wstr.push(cloned);
1003 ///
1004 /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString");
1005 /// ```
1006 fn push() -> {}
1007
1008 /// Extends the string with the given slice.
1009 ///
1010 /// No checks are performed on the strings. It is possible to end up nul values inside
1011 /// the string, or invalid encoding, and it is up to the caller to determine if that is
1012 /// acceptable.
1013 ///
1014 /// # Examples
1015 ///
1016 /// ```rust
1017 /// use widestring::U16String;
1018 /// let s = "MyString";
1019 /// let mut wstr = U16String::from_str(s);
1020 /// let cloned = wstr.clone();
1021 /// // Push the clone to the end, repeating the string twice.
1022 /// wstr.push_slice(cloned);
1023 ///
1024 /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString");
1025 /// ```
1026 fn push_slice() -> {}
1027
1028 /// Converts this wide string into a boxed string slice.
1029 ///
1030 /// # Examples
1031 ///
1032 /// ```
1033 /// use widestring::{U16String, U16Str};
1034 ///
1035 /// let s = U16String::from_str("hello");
1036 ///
1037 /// let b: Box<U16Str> = s.into_boxed_ustr();
1038 /// ```
1039 fn into_boxed_ustr() -> {}
1040}
1041
1042ustring_common_impl! {
1043 /// An owned, mutable 32-bit wide string with undefined encoding.
1044 ///
1045 /// The string slice of a [`U32String`] is [`U32Str`].
1046 ///
1047 /// [`U32String`] are strings that do not have a defined encoding. While it is sometimes
1048 /// assumed that they contain possibly invalid or ill-formed UTF-32 data, they may be used for
1049 /// any wide encoded string. This is because [`U32String`] is intended to be used with FFI
1050 /// functions, where proper encoding cannot be guaranteed. If you need string slices that are
1051 /// always valid UTF-32 strings, use [`Utf32String`][crate::Utf32String] instead.
1052 ///
1053 /// Because [`U32String`] does not have a defined encoding, no restrictions are placed on
1054 /// mutating or indexing the string. This means that even if the string contained properly
1055 /// encoded UTF-32 or other encoding data, mutationing or indexing may result in malformed data.
1056 /// Convert to a [`Utf32String`][crate::Utf32String] if retaining proper UTF-16 encoding is
1057 /// desired.
1058 ///
1059 /// # FFI considerations
1060 ///
1061 /// [`U32String`] is not aware of nul values. Strings may or may not be nul-terminated, and may
1062 /// contain invalid and ill-formed UTF-32. These strings are intended to be used with FFI functions
1063 /// that directly use string length, where the strings are known to have proper nul-termination
1064 /// already, or where strings are merely being passed through without modification.
1065 ///
1066 /// [`U32CString`][crate::U32CString] should be used instead if nul-aware strings are required.
1067 ///
1068 /// # Examples
1069 ///
1070 /// The easiest way to use [`U32String`] outside of FFI is with the [`u32str!`][crate::u32str]
1071 /// macro to convert string literals into UTF-32 string slices at compile time:
1072 ///
1073 /// ```
1074 /// use widestring::{u32str, U32String};
1075 /// let hello = U32String::from(u32str!("Hello, world!"));
1076 /// ```
1077 ///
1078 /// You can also convert any [`u32`] slice or vector directly:
1079 ///
1080 /// ```
1081 /// use widestring::{u32str, U32String};
1082 ///
1083 /// let sparkle_heart = vec![0x1f496];
1084 /// let sparkle_heart = U32String::from_vec(sparkle_heart);
1085 ///
1086 /// assert_eq!(u32str!("💖"), sparkle_heart);
1087 ///
1088 /// // This UTf-16 surrogate is invalid UTF-32, but is perfectly valid in U32String
1089 /// let malformed_utf32 = vec![0x0, 0xd83d]; // Note that nul values are also valid an untouched
1090 /// let s = U32String::from_vec(malformed_utf32);
1091 ///
1092 /// assert_eq!(s.len(), 2);
1093 /// ```
1094 ///
1095 /// The following example constructs a [`U32String`] and shows how to convert a [`U32String`] to
1096 /// a regular Rust [`String`].
1097 ///
1098 /// ```rust
1099 /// use widestring::U32String;
1100 /// let s = "Test";
1101 /// // Create a wide string from the rust string
1102 /// let wstr = U32String::from_str(s);
1103 /// // Convert back to a rust string
1104 /// let rust_str = wstr.to_string_lossy();
1105 /// assert_eq!(rust_str, "Test");
1106 /// ```
1107 struct U32String([u32]);
1108
1109 type UStr = U32Str;
1110 type UCString = U32CString;
1111 type UCStr = U32CStr;
1112 type UtfStr = Utf32Str;
1113 type UtfString = Utf32String;
1114
1115 /// Extends the string with the given string slice.
1116 ///
1117 /// No checks are performed on the strings. It is possible to end up nul values inside
1118 /// the string, or invalid encoding, and it is up to the caller to determine if that is
1119 /// acceptable.
1120 ///
1121 /// # Examples
1122 ///
1123 /// ```rust
1124 /// use widestring::U32String;
1125 /// let s = "MyString";
1126 /// let mut wstr = U32String::from_str(s);
1127 /// let cloned = wstr.clone();
1128 /// // Push the clone to the end, repeating the string twice.
1129 /// wstr.push(cloned);
1130 ///
1131 /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString");
1132 /// ```
1133 fn push() -> {}
1134
1135 /// Extends the string with the given slice.
1136 ///
1137 /// No checks are performed on the strings. It is possible to end up nul values inside
1138 /// the string, or invalid encoding, and it is up to the caller to determine if that is
1139 /// acceptable.
1140 ///
1141 /// # Examples
1142 ///
1143 /// ```rust
1144 /// use widestring::U32String;
1145 /// let s = "MyString";
1146 /// let mut wstr = U32String::from_str(s);
1147 /// let cloned = wstr.clone();
1148 /// // Push the clone to the end, repeating the string twice.
1149 /// wstr.push_slice(cloned);
1150 ///
1151 /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString");
1152 /// ```
1153 fn push_slice() -> {}
1154
1155 /// Converts this wide string into a boxed string slice.
1156 ///
1157 /// # Examples
1158 ///
1159 /// ```
1160 /// use widestring::{U32String, U32Str};
1161 ///
1162 /// let s = U32String::from_str("hello");
1163 ///
1164 /// let b: Box<U32Str> = s.into_boxed_ustr();
1165 /// ```
1166 fn into_boxed_ustr() -> {}
1167}
1168
1169impl U16String {
1170 /// Constructs a [`U16String`] copy from a [`str`], encoding it as UTF-16.
1171 ///
1172 /// This makes a string copy of the [`str`]. Since [`str`] will always be valid UTF-8, the
1173 /// resulting [`U16String`] will also be valid UTF-16.
1174 ///
1175 /// # Examples
1176 ///
1177 /// ```rust
1178 /// use widestring::U16String;
1179 /// let s = "MyString";
1180 /// // Create a wide string from the string
1181 /// let wstr = U16String::from_str(s);
1182 ///
1183 /// assert_eq!(wstr.to_string().unwrap(), s);
1184 /// ```
1185 #[allow(clippy::should_implement_trait)]
1186 #[inline]
1187 #[must_use]
1188 pub fn from_str<S: AsRef<str> + ?Sized>(s: &S) -> Self {
1189 Self {
1190 inner: s.as_ref().encode_utf16().collect(),
1191 }
1192 }
1193
1194 /// Constructs a [`U16String`] copy from an [`OsStr`][std::ffi::OsStr].
1195 ///
1196 /// This makes a string copy of the [`OsStr`][std::ffi::OsStr]. Since [`OsStr`][std::ffi::OsStr]
1197 /// makes no guarantees that it is valid data, there is no guarantee that the resulting
1198 /// [`U16String`] will be valid UTF-16.
1199 ///
1200 /// Note that the encoding of [`OsStr`][std::ffi::OsStr] is platform-dependent, so on
1201 /// some platforms this may make an encoding conversions, while on other platforms (such as
1202 /// windows) no changes to the string will be made.
1203 ///
1204 /// # Examples
1205 ///
1206 /// ```rust
1207 /// use widestring::U16String;
1208 /// let s = "MyString";
1209 /// // Create a wide string from the string
1210 /// let wstr = U16String::from_os_str(s);
1211 ///
1212 /// assert_eq!(wstr.to_string().unwrap(), s);
1213 /// ```
1214 #[cfg(feature = "std")]
1215 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1216 #[inline]
1217 #[must_use]
1218 pub fn from_os_str<S: AsRef<std::ffi::OsStr> + ?Sized>(s: &S) -> Self {
1219 Self {
1220 inner: crate::platform::os_to_wide(s.as_ref()),
1221 }
1222 }
1223
1224 /// Extends the string with the given string slice, encoding it at UTF-16.
1225 ///
1226 /// No checks are performed on the strings. It is possible to end up nul values inside the
1227 /// string, and it is up to the caller to determine if that is acceptable.
1228 ///
1229 /// # Examples
1230 ///
1231 /// ```rust
1232 /// use widestring::U16String;
1233 /// let s = "MyString";
1234 /// let mut wstr = U16String::from_str(s);
1235 /// // Push the original to the end, repeating the string twice.
1236 /// wstr.push_str(s);
1237 ///
1238 /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString");
1239 /// ```
1240 #[inline]
1241 pub fn push_str(&mut self, s: impl AsRef<str>) {
1242 self.inner.extend(s.as_ref().encode_utf16())
1243 }
1244
1245 /// Extends the string with the given string slice.
1246 ///
1247 /// No checks are performed on the strings. It is possible to end up nul values inside the
1248 /// string, and it is up to the caller to determine if that is acceptable.
1249 ///
1250 /// # Examples
1251 ///
1252 /// ```rust
1253 /// use widestring::U16String;
1254 /// let s = "MyString";
1255 /// let mut wstr = U16String::from_str(s);
1256 /// // Push the original to the end, repeating the string twice.
1257 /// wstr.push_os_str(s);
1258 ///
1259 /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString");
1260 /// ```
1261 #[cfg(feature = "std")]
1262 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1263 #[inline]
1264 pub fn push_os_str(&mut self, s: impl AsRef<std::ffi::OsStr>) {
1265 self.inner.extend(crate::platform::os_to_wide(s.as_ref()))
1266 }
1267
1268 /// Appends the given [`char`][prim@char] encoded as UTF-16 to the end of this string.
1269 #[inline]
1270 pub fn push_char(&mut self, c: char) {
1271 let mut buf = [0; 2];
1272 self.inner.extend_from_slice(c.encode_utf16(&mut buf))
1273 }
1274
1275 /// Removes the last character or unpaired surrogate from the string buffer and returns it.
1276 ///
1277 /// This method assumes UTF-16 encoding, but handles invalid UTF-16 by returning unpaired
1278 /// surrogates.
1279 ///
1280 /// Returns `None` if this String is empty. Otherwise, returns the character cast to a
1281 /// [`u32`][prim@u32] or the value of the unpaired surrogate as a [`u32`][prim@u32] value.
1282 pub fn pop_char(&mut self) -> Option<u32> {
1283 match self.inner.pop() {
1284 Some(low) if crate::is_utf16_surrogate(low) => {
1285 if !crate::is_utf16_low_surrogate(low) || self.inner.is_empty() {
1286 Some(low as u32)
1287 } else {
1288 let high = self.inner[self.len() - 1];
1289 if crate::is_utf16_high_surrogate(high) {
1290 self.inner.pop();
1291 let buf = [high, low];
1292 Some(
1293 char::decode_utf16(buf.iter().copied())
1294 .next()
1295 .unwrap()
1296 .unwrap() as u32,
1297 )
1298 } else {
1299 Some(low as u32)
1300 }
1301 }
1302 }
1303 Some(u) => Some(u as u32),
1304 None => None,
1305 }
1306 }
1307
1308 /// Removes a [`char`][prim@char] or unpaired surrogate from this string at a position and
1309 /// returns it as a [`u32`][prim@u32].
1310 ///
1311 /// This method assumes UTF-16 encoding, but handles invalid UTF-16 by returning unpaired
1312 /// surrogates.
1313 ///
1314 /// This is an _O(n)_ operation, as it requires copying every element in the buffer.
1315 ///
1316 /// # Panics
1317 ///
1318 /// Panics if `idx` is larger than or equal to the string's length.
1319 pub fn remove_char(&mut self, idx: usize) -> u32 {
1320 let slice = &self.inner[idx..];
1321 let c = char::decode_utf16(slice.iter().copied()).next().unwrap();
1322 let clen = c.as_ref().map(|c| c.len_utf16()).unwrap_or(1);
1323 let c = c
1324 .map(|c| c as u32)
1325 .unwrap_or_else(|_| self.inner[idx] as u32);
1326 self.inner.drain(idx..idx + clen);
1327 c
1328 }
1329
1330 /// Inserts a character encoded as UTF-16 into this string at a specified position.
1331 ///
1332 /// This is an _O(n)_ operation as it requires copying every element in the buffer.
1333 ///
1334 /// # Panics
1335 ///
1336 /// Panics if `idx` is larger than the string's length.
1337 pub fn insert_char(&mut self, idx: usize, c: char) {
1338 assert!(idx <= self.len());
1339 let mut buf = [0; 2];
1340 let slice = c.encode_utf16(&mut buf);
1341 self.inner.resize(self.len() + slice.len(), 0);
1342 self.inner.copy_within(idx.., idx + slice.len());
1343 self.inner[idx..].copy_from_slice(slice);
1344 }
1345}
1346
1347impl U32String {
1348 /// Constructs a [`U32String`] from a [`char`][prim@char] vector.
1349 ///
1350 /// No checks are made on the contents of the vector.
1351 ///
1352 /// # Examples
1353 ///
1354 /// ```rust
1355 /// use widestring::U32String;
1356 /// let v: Vec<char> = "Test".chars().collect();
1357 /// # let cloned: Vec<u32> = v.iter().map(|&c| c as u32).collect();
1358 /// // Create a wide string from the vector
1359 /// let wstr = U32String::from_chars(v);
1360 /// # assert_eq!(wstr.into_vec(), cloned);
1361 /// ```
1362 #[must_use]
1363 pub fn from_chars(raw: impl Into<Vec<char>>) -> Self {
1364 let mut chars = raw.into();
1365 Self {
1366 inner: unsafe {
1367 let ptr = chars.as_mut_ptr() as *mut u32;
1368 let len = chars.len();
1369 let cap = chars.capacity();
1370 mem::forget(chars);
1371 Vec::from_raw_parts(ptr, len, cap)
1372 },
1373 }
1374 }
1375
1376 /// Constructs a [`U16String`] copy from a [`str`], encoding it as UTF-32.
1377 ///
1378 /// This makes a string copy of the [`str`]. Since [`str`] will always be valid UTF-8, the
1379 /// resulting [`U32String`] will also be valid UTF-32.
1380 ///
1381 /// # Examples
1382 ///
1383 /// ```rust
1384 /// use widestring::U32String;
1385 /// let s = "MyString";
1386 /// // Create a wide string from the string
1387 /// let wstr = U32String::from_str(s);
1388 ///
1389 /// assert_eq!(wstr.to_string().unwrap(), s);
1390 /// ```
1391 #[allow(clippy::should_implement_trait)]
1392 #[inline]
1393 #[must_use]
1394 pub fn from_str<S: AsRef<str> + ?Sized>(s: &S) -> Self {
1395 let v: Vec<char> = s.as_ref().chars().collect();
1396 Self::from_chars(v)
1397 }
1398
1399 /// Constructs a [`U32String`] copy from an [`OsStr`][std::ffi::OsStr].
1400 ///
1401 /// This makes a string copy of the [`OsStr`][std::ffi::OsStr]. Since [`OsStr`][std::ffi::OsStr]
1402 /// makes no guarantees that it is valid data, there is no guarantee that the resulting
1403 /// [`U32String`] will be valid UTF-32.
1404 ///
1405 /// Note that the encoding of [`OsStr`][std::ffi::OsStr] is platform-dependent, so on
1406 /// some platforms this may make an encoding conversions, while on other platforms no changes to
1407 /// the string will be made.
1408 ///
1409 /// # Examples
1410 ///
1411 /// ```rust
1412 /// use widestring::U32String;
1413 /// let s = "MyString";
1414 /// // Create a wide string from the string
1415 /// let wstr = U32String::from_os_str(s);
1416 ///
1417 /// assert_eq!(wstr.to_string().unwrap(), s);
1418 /// ```
1419 #[cfg(feature = "std")]
1420 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1421 #[must_use]
1422 pub fn from_os_str<S: AsRef<std::ffi::OsStr> + ?Sized>(s: &S) -> Self {
1423 let v: Vec<char> = s.as_ref().to_string_lossy().chars().collect();
1424 Self::from_chars(v)
1425 }
1426
1427 /// Constructs a [`U32String`] from a [`char`][prim@char] pointer and a length.
1428 ///
1429 /// The `len` argument is the number of `char` elements, **not** the number of bytes.
1430 ///
1431 /// # Safety
1432 ///
1433 /// This function is unsafe as there is no guarantee that the given pointer is valid for `len`
1434 /// elements.
1435 ///
1436 /// In addition, the data must meet the safety conditions of [std::slice::from_raw_parts].
1437 ///
1438 /// # Panics
1439 ///
1440 /// Panics if `len` is greater than 0 but `p` is a null pointer.
1441 #[inline]
1442 #[must_use]
1443 pub unsafe fn from_char_ptr(p: *const char, len: usize) -> Self {
1444 Self::from_ptr(p as *const u32, len)
1445 }
1446
1447 /// Extends the string with the given string slice, encoding it at UTF-32.
1448 ///
1449 /// No checks are performed on the strings. It is possible to end up nul values inside the
1450 /// string, and it is up to the caller to determine if that is acceptable.
1451 ///
1452 /// # Examples
1453 ///
1454 /// ```rust
1455 /// use widestring::U32String;
1456 /// let s = "MyString";
1457 /// let mut wstr = U32String::from_str(s);
1458 /// // Push the original to the end, repeating the string twice.
1459 /// wstr.push_str(s);
1460 ///
1461 /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString");
1462 /// ```
1463 #[inline]
1464 pub fn push_str(&mut self, s: impl AsRef<str>) {
1465 self.inner.extend(s.as_ref().chars().map(|c| c as u32))
1466 }
1467
1468 /// Extends the string with the given string slice.
1469 ///
1470 /// No checks are performed on the strings. It is possible to end up nul values inside the
1471 /// string, and it is up to the caller to determine if that is acceptable.
1472 ///
1473 /// # Examples
1474 ///
1475 /// ```rust
1476 /// use widestring::U32String;
1477 /// let s = "MyString";
1478 /// let mut wstr = U32String::from_str(s);
1479 /// // Push the original to the end, repeating the string twice.
1480 /// wstr.push_os_str(s);
1481 ///
1482 /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString");
1483 /// ```
1484 #[cfg(feature = "std")]
1485 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1486 #[inline]
1487 pub fn push_os_str(&mut self, s: impl AsRef<std::ffi::OsStr>) {
1488 self.inner
1489 .extend(s.as_ref().to_string_lossy().chars().map(|c| c as u32))
1490 }
1491
1492 /// Appends the given [`char`][prim@char] encoded as UTF-32 to the end of this string.
1493 #[inline]
1494 pub fn push_char(&mut self, c: char) {
1495 self.inner.push(c as u32);
1496 }
1497
1498 /// Removes the last value from the string buffer and returns it.
1499 ///
1500 /// This method assumes UTF-32 encoding.
1501 ///
1502 /// Returns `None` if this String is empty.
1503 #[inline]
1504 pub fn pop_char(&mut self) -> Option<u32> {
1505 self.inner.pop()
1506 }
1507
1508 /// Removes a value from this string at a position and returns it.
1509 ///
1510 /// This method assumes UTF-32 encoding.
1511 ///
1512 /// This is an _O(n)_ operation, as it requires copying every element in the buffer.
1513 ///
1514 /// # Panics
1515 ///
1516 /// Panics if `idx` is larger than or equal to the string's length.
1517 #[inline]
1518 pub fn remove_char(&mut self, idx: usize) -> u32 {
1519 self.inner.remove(idx)
1520 }
1521
1522 /// Inserts a character encoded as UTF-32 into this string at a specified position.
1523 ///
1524 /// This is an _O(n)_ operation as it requires copying every element in the buffer.
1525 ///
1526 /// # Panics
1527 ///
1528 /// Panics if `idx` is larger than the string's length.
1529 #[inline]
1530 pub fn insert_char(&mut self, idx: usize, c: char) {
1531 self.inner.insert(idx, c as u32)
1532 }
1533}
1534
1535impl core::fmt::Debug for U16String {
1536 #[inline]
1537 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1538 crate::debug_fmt_u16(self.as_slice(), f)
1539 }
1540}
1541
1542impl core::fmt::Debug for U32String {
1543 #[inline]
1544 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1545 crate::debug_fmt_u32(self.as_slice(), f)
1546 }
1547}
1548
1549impl From<Vec<char>> for U32String {
1550 #[inline]
1551 fn from(value: Vec<char>) -> Self {
1552 Self::from_chars(value)
1553 }
1554}
1555
1556impl From<&[char]> for U32String {
1557 #[inline]
1558 fn from(value: &[char]) -> Self {
1559 U32String::from_chars(value)
1560 }
1561}
1562
1563/// Alias for [`U16String`] or [`U32String`] depending on platform. Intended to match typical C
1564/// `wchar_t` size on platform.
1565#[cfg(not(windows))]
1566pub type WideString = U32String;
1567
1568/// Alias for [`U16String`] or [`U32String`] depending on platform. Intended to match typical C
1569/// `wchar_t` size on platform.
1570#[cfg(windows)]
1571pub type WideString = U16String;
1572
1573#[cfg(test)]
1574mod test {
1575 use super::*;
1576
1577 #[test]
1578 #[allow(clippy::write_literal)]
1579 fn number_to_string() {
1580 let mut s = U16String::new();
1581 write!(s, "{}", 1234).unwrap();
1582 assert_eq!(s, U16String::from_str("1234"));
1583 }
1584
1585 #[test]
1586 fn truncated_with_surrogate() {
1587 // Character U+24B62, encoded as D852 DF62 in UTF16
1588 let buf = "ð¤¢";
1589 let mut s = U16String::from_str(buf);
1590 assert_eq!(s.pop_char(), Some('ð¤¢' as u32));
1591 }
1592}