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 core::clone::CloneToUninit;
4
5use crate::borrow::Cow;
6use crate::collections::TryReserveError;
7use crate::rc::Rc;
8use crate::sync::Arc;
9use crate::sys_common::wtf8::{Wtf8, Wtf8Buf, check_utf8_boundary};
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        self.inner.extend_from_slice(other);
224    }
225}
226
227impl Slice {
228    #[inline]
229    pub fn as_encoded_bytes(&self) -> &[u8] {
230        self.inner.as_bytes()
231    }
232
233    #[inline]
234    pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice {
235        unsafe { mem::transmute(Wtf8::from_bytes_unchecked(s)) }
236    }
237
238    #[track_caller]
239    #[inline]
240    pub fn check_public_boundary(&self, index: usize) {
241        check_utf8_boundary(&self.inner, index);
242    }
243
244    #[inline]
245    pub fn from_str(s: &str) -> &Slice {
246        unsafe { mem::transmute(Wtf8::from_str(s)) }
247    }
248
249    #[inline]
250    pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
251        self.inner.as_str()
252    }
253
254    #[inline]
255    pub fn to_string_lossy(&self) -> Cow<'_, str> {
256        self.inner.to_string_lossy()
257    }
258
259    #[inline]
260    pub fn to_owned(&self) -> Buf {
261        Buf { inner: self.inner.to_owned() }
262    }
263
264    #[inline]
265    pub fn clone_into(&self, buf: &mut Buf) {
266        self.inner.clone_into(&mut buf.inner)
267    }
268
269    #[inline]
270    pub fn into_box(&self) -> Box<Slice> {
271        unsafe { mem::transmute(self.inner.into_box()) }
272    }
273
274    #[inline]
275    pub fn empty_box() -> Box<Slice> {
276        unsafe { mem::transmute(Wtf8::empty_box()) }
277    }
278
279    #[inline]
280    pub fn into_arc(&self) -> Arc<Slice> {
281        let arc = self.inner.into_arc();
282        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
283    }
284
285    #[inline]
286    pub fn into_rc(&self) -> Rc<Slice> {
287        let rc = self.inner.into_rc();
288        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
289    }
290
291    #[inline]
292    pub fn make_ascii_lowercase(&mut self) {
293        self.inner.make_ascii_lowercase()
294    }
295
296    #[inline]
297    pub fn make_ascii_uppercase(&mut self) {
298        self.inner.make_ascii_uppercase()
299    }
300
301    #[inline]
302    pub fn to_ascii_lowercase(&self) -> Buf {
303        Buf { inner: self.inner.to_ascii_lowercase() }
304    }
305
306    #[inline]
307    pub fn to_ascii_uppercase(&self) -> Buf {
308        Buf { inner: self.inner.to_ascii_uppercase() }
309    }
310
311    #[inline]
312    pub fn is_ascii(&self) -> bool {
313        self.inner.is_ascii()
314    }
315
316    #[inline]
317    pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
318        self.inner.eq_ignore_ascii_case(&other.inner)
319    }
320}
321
322#[unstable(feature = "clone_to_uninit", issue = "126799")]
323unsafe impl CloneToUninit for Slice {
324    #[inline]
325    #[cfg_attr(debug_assertions, track_caller)]
326    unsafe fn clone_to_uninit(&self, dst: *mut u8) {
327        // SAFETY: we're just a transparent wrapper around Wtf8
328        unsafe { self.inner.clone_to_uninit(dst) }
329    }
330}