std\sys\os_str/
wtf8.rs

1//! The underlying OsString/OsStr implementation on Windows is a
2//! wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
3use alloc::wtf8::{Wtf8, Wtf8Buf};
4use core::clone::CloneToUninit;
5
6use crate::borrow::Cow;
7use crate::collections::TryReserveError;
8use crate::rc::Rc;
9use crate::sync::Arc;
10use crate::sys_common::{AsInner, FromInner, IntoInner};
11use crate::{fmt, mem};
12
13#[derive(Hash)]
14pub struct Buf {
15    pub inner: Wtf8Buf,
16}
17
18#[repr(transparent)]
19pub struct Slice {
20    pub inner: Wtf8,
21}
22
23impl IntoInner<Wtf8Buf> for Buf {
24    fn into_inner(self) -> Wtf8Buf {
25        self.inner
26    }
27}
28
29impl FromInner<Wtf8Buf> for Buf {
30    fn from_inner(inner: Wtf8Buf) -> Self {
31        Buf { inner }
32    }
33}
34
35impl AsInner<Wtf8> for Buf {
36    #[inline]
37    fn as_inner(&self) -> &Wtf8 {
38        &self.inner
39    }
40}
41
42impl fmt::Debug for Buf {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        fmt::Debug::fmt(&self.inner, f)
45    }
46}
47
48impl fmt::Display for Buf {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        fmt::Display::fmt(&self.inner, f)
51    }
52}
53
54impl fmt::Debug for Slice {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        fmt::Debug::fmt(&self.inner, f)
57    }
58}
59
60impl fmt::Display for Slice {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        fmt::Display::fmt(&self.inner, f)
63    }
64}
65
66impl Clone for Buf {
67    #[inline]
68    fn clone(&self) -> Self {
69        Buf { inner: self.inner.clone() }
70    }
71
72    #[inline]
73    fn clone_from(&mut self, source: &Self) {
74        self.inner.clone_from(&source.inner)
75    }
76}
77
78impl Buf {
79    #[inline]
80    pub fn into_encoded_bytes(self) -> Vec<u8> {
81        self.inner.into_bytes()
82    }
83
84    #[inline]
85    pub unsafe fn from_encoded_bytes_unchecked(s: Vec<u8>) -> Self {
86        unsafe { Self { inner: Wtf8Buf::from_bytes_unchecked(s) } }
87    }
88
89    #[inline]
90    pub fn into_string(self) -> Result<String, Buf> {
91        self.inner.into_string().map_err(|buf| Buf { inner: buf })
92    }
93
94    #[inline]
95    pub const fn from_string(s: String) -> Buf {
96        Buf { inner: Wtf8Buf::from_string(s) }
97    }
98
99    #[inline]
100    pub fn with_capacity(capacity: usize) -> Buf {
101        Buf { inner: Wtf8Buf::with_capacity(capacity) }
102    }
103
104    #[inline]
105    pub fn clear(&mut self) {
106        self.inner.clear()
107    }
108
109    #[inline]
110    pub fn capacity(&self) -> usize {
111        self.inner.capacity()
112    }
113
114    #[inline]
115    pub fn push_slice(&mut self, s: &Slice) {
116        self.inner.push_wtf8(&s.inner)
117    }
118
119    #[inline]
120    pub fn push_str(&mut self, s: &str) {
121        self.inner.push_str(s);
122    }
123
124    #[inline]
125    pub fn reserve(&mut self, additional: usize) {
126        self.inner.reserve(additional)
127    }
128
129    #[inline]
130    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
131        self.inner.try_reserve(additional)
132    }
133
134    #[inline]
135    pub fn reserve_exact(&mut self, additional: usize) {
136        self.inner.reserve_exact(additional)
137    }
138
139    #[inline]
140    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
141        self.inner.try_reserve_exact(additional)
142    }
143
144    #[inline]
145    pub fn shrink_to_fit(&mut self) {
146        self.inner.shrink_to_fit()
147    }
148
149    #[inline]
150    pub fn shrink_to(&mut self, min_capacity: usize) {
151        self.inner.shrink_to(min_capacity)
152    }
153
154    #[inline]
155    pub fn as_slice(&self) -> &Slice {
156        // SAFETY: Slice is just a wrapper for Wtf8,
157        // and self.inner.as_slice() returns &Wtf8.
158        // Therefore, transmuting &Wtf8 to &Slice is safe.
159        unsafe { mem::transmute(self.inner.as_slice()) }
160    }
161
162    #[inline]
163    pub fn as_mut_slice(&mut self) -> &mut Slice {
164        // SAFETY: Slice is just a wrapper for Wtf8,
165        // and self.inner.as_mut_slice() returns &mut Wtf8.
166        // Therefore, transmuting &mut Wtf8 to &mut Slice is safe.
167        // Additionally, care should be taken to ensure the slice
168        // is always valid Wtf8.
169        unsafe { mem::transmute(self.inner.as_mut_slice()) }
170    }
171
172    #[inline]
173    pub fn leak<'a>(self) -> &'a mut Slice {
174        unsafe { mem::transmute(self.inner.leak()) }
175    }
176
177    #[inline]
178    pub fn into_box(self) -> Box<Slice> {
179        unsafe { mem::transmute(self.inner.into_box()) }
180    }
181
182    #[inline]
183    pub fn from_box(boxed: Box<Slice>) -> Buf {
184        let inner: Box<Wtf8> = unsafe { mem::transmute(boxed) };
185        Buf { inner: Wtf8Buf::from_box(inner) }
186    }
187
188    #[inline]
189    pub fn into_arc(&self) -> Arc<Slice> {
190        self.as_slice().into_arc()
191    }
192
193    #[inline]
194    pub fn into_rc(&self) -> Rc<Slice> {
195        self.as_slice().into_rc()
196    }
197
198    /// Provides plumbing to `Vec::truncate` without giving full mutable access
199    /// to the `Vec`.
200    ///
201    /// # Safety
202    ///
203    /// The length must be at an `OsStr` boundary, according to
204    /// `Slice::check_public_boundary`.
205    #[inline]
206    pub unsafe fn truncate_unchecked(&mut self, len: usize) {
207        self.inner.truncate(len);
208    }
209
210    /// Provides plumbing to `Vec::extend_from_slice` without giving full
211    /// mutable access to the `Vec`.
212    ///
213    /// # Safety
214    ///
215    /// The slice must be valid for the platform encoding (as described in
216    /// [`Slice::from_encoded_bytes_unchecked`]).
217    ///
218    /// This bypasses the WTF-8 surrogate joining, so either `self` must not
219    /// end with a leading surrogate half, or `other` must not start with a
220    /// trailing surrogate half.
221    #[inline]
222    pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
223        unsafe {
224            self.inner.extend_from_slice_unchecked(other);
225        }
226    }
227}
228
229impl Slice {
230    #[inline]
231    pub fn as_encoded_bytes(&self) -> &[u8] {
232        self.inner.as_bytes()
233    }
234
235    #[inline]
236    pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice {
237        unsafe { mem::transmute(Wtf8::from_bytes_unchecked(s)) }
238    }
239
240    #[track_caller]
241    #[inline]
242    pub fn check_public_boundary(&self, index: usize) {
243        self.inner.check_utf8_boundary(index);
244    }
245
246    #[inline]
247    pub fn from_str(s: &str) -> &Slice {
248        unsafe { mem::transmute(Wtf8::from_str(s)) }
249    }
250
251    #[inline]
252    pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
253        self.inner.as_str()
254    }
255
256    #[inline]
257    pub fn to_string_lossy(&self) -> Cow<'_, str> {
258        self.inner.to_string_lossy()
259    }
260
261    #[inline]
262    pub fn to_owned(&self) -> Buf {
263        Buf { inner: self.inner.to_owned() }
264    }
265
266    #[inline]
267    pub fn clone_into(&self, buf: &mut Buf) {
268        self.inner.clone_into(&mut buf.inner)
269    }
270
271    #[inline]
272    pub fn into_box(&self) -> Box<Slice> {
273        unsafe { mem::transmute(self.inner.into_box()) }
274    }
275
276    #[inline]
277    pub fn empty_box() -> Box<Slice> {
278        unsafe { mem::transmute(Wtf8::empty_box()) }
279    }
280
281    #[inline]
282    pub fn into_arc(&self) -> Arc<Slice> {
283        let arc = self.inner.into_arc();
284        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
285    }
286
287    #[inline]
288    pub fn into_rc(&self) -> Rc<Slice> {
289        let rc = self.inner.into_rc();
290        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
291    }
292
293    #[inline]
294    pub fn make_ascii_lowercase(&mut self) {
295        self.inner.make_ascii_lowercase()
296    }
297
298    #[inline]
299    pub fn make_ascii_uppercase(&mut self) {
300        self.inner.make_ascii_uppercase()
301    }
302
303    #[inline]
304    pub fn to_ascii_lowercase(&self) -> Buf {
305        Buf { inner: self.inner.to_ascii_lowercase() }
306    }
307
308    #[inline]
309    pub fn to_ascii_uppercase(&self) -> Buf {
310        Buf { inner: self.inner.to_ascii_uppercase() }
311    }
312
313    #[inline]
314    pub fn is_ascii(&self) -> bool {
315        self.inner.is_ascii()
316    }
317
318    #[inline]
319    pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
320        self.inner.eq_ignore_ascii_case(&other.inner)
321    }
322}
323
324#[unstable(feature = "clone_to_uninit", issue = "126799")]
325unsafe impl CloneToUninit for Slice {
326    #[inline]
327    #[cfg_attr(debug_assertions, track_caller)]
328    unsafe fn clone_to_uninit(&self, dst: *mut u8) {
329        // SAFETY: we're just a transparent wrapper around Wtf8
330        unsafe { self.inner.clone_to_uninit(dst) }
331    }
332}