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 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 core `Vec::truncate`.
199    /// More well behaving alternative to allowing outer types
200    /// full mutable access to the core `Vec`.
201    #[inline]
202    pub(crate) fn truncate(&mut self, len: usize) {
203        self.inner.truncate(len);
204    }
205
206    /// Provides plumbing to core `Vec::extend_from_slice`.
207    /// More well behaving alternative to allowing outer types
208    /// full mutable access to the core `Vec`.
209    #[inline]
210    pub(crate) fn extend_from_slice(&mut self, other: &[u8]) {
211        self.inner.extend_from_slice(other);
212    }
213}
214
215impl Slice {
216    #[inline]
217    pub fn as_encoded_bytes(&self) -> &[u8] {
218        self.inner.as_bytes()
219    }
220
221    #[inline]
222    pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice {
223        unsafe { mem::transmute(Wtf8::from_bytes_unchecked(s)) }
224    }
225
226    #[track_caller]
227    #[inline]
228    pub fn check_public_boundary(&self, index: usize) {
229        check_utf8_boundary(&self.inner, index);
230    }
231
232    #[inline]
233    pub fn from_str(s: &str) -> &Slice {
234        unsafe { mem::transmute(Wtf8::from_str(s)) }
235    }
236
237    #[inline]
238    pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
239        self.inner.as_str()
240    }
241
242    #[inline]
243    pub fn to_string_lossy(&self) -> Cow<'_, str> {
244        self.inner.to_string_lossy()
245    }
246
247    #[inline]
248    pub fn to_owned(&self) -> Buf {
249        Buf { inner: self.inner.to_owned() }
250    }
251
252    #[inline]
253    pub fn clone_into(&self, buf: &mut Buf) {
254        self.inner.clone_into(&mut buf.inner)
255    }
256
257    #[inline]
258    pub fn into_box(&self) -> Box<Slice> {
259        unsafe { mem::transmute(self.inner.into_box()) }
260    }
261
262    #[inline]
263    pub fn empty_box() -> Box<Slice> {
264        unsafe { mem::transmute(Wtf8::empty_box()) }
265    }
266
267    #[inline]
268    pub fn into_arc(&self) -> Arc<Slice> {
269        let arc = self.inner.into_arc();
270        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
271    }
272
273    #[inline]
274    pub fn into_rc(&self) -> Rc<Slice> {
275        let rc = self.inner.into_rc();
276        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
277    }
278
279    #[inline]
280    pub fn make_ascii_lowercase(&mut self) {
281        self.inner.make_ascii_lowercase()
282    }
283
284    #[inline]
285    pub fn make_ascii_uppercase(&mut self) {
286        self.inner.make_ascii_uppercase()
287    }
288
289    #[inline]
290    pub fn to_ascii_lowercase(&self) -> Buf {
291        Buf { inner: self.inner.to_ascii_lowercase() }
292    }
293
294    #[inline]
295    pub fn to_ascii_uppercase(&self) -> Buf {
296        Buf { inner: self.inner.to_ascii_uppercase() }
297    }
298
299    #[inline]
300    pub fn is_ascii(&self) -> bool {
301        self.inner.is_ascii()
302    }
303
304    #[inline]
305    pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
306        self.inner.eq_ignore_ascii_case(&other.inner)
307    }
308}
309
310#[unstable(feature = "clone_to_uninit", issue = "126799")]
311unsafe impl CloneToUninit for Slice {
312    #[inline]
313    #[cfg_attr(debug_assertions, track_caller)]
314    unsafe fn clone_to_uninit(&self, dst: *mut u8) {
315        // SAFETY: we're just a transparent wrapper around Wtf8
316        unsafe { self.inner.clone_to_uninit(dst) }
317    }
318}