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(Clone, Hash)]
14pub struct Buf {
15    pub inner: Wtf8Buf,
16}
17
18impl IntoInner<Wtf8Buf> for Buf {
19    fn into_inner(self) -> Wtf8Buf {
20        self.inner
21    }
22}
23
24impl FromInner<Wtf8Buf> for Buf {
25    fn from_inner(inner: Wtf8Buf) -> Self {
26        Buf { inner }
27    }
28}
29
30impl AsInner<Wtf8> for Buf {
31    #[inline]
32    fn as_inner(&self) -> &Wtf8 {
33        &self.inner
34    }
35}
36
37impl fmt::Debug for Buf {
38    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
39        fmt::Debug::fmt(self.as_slice(), formatter)
40    }
41}
42
43impl fmt::Display for Buf {
44    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
45        fmt::Display::fmt(self.as_slice(), formatter)
46    }
47}
48
49#[repr(transparent)]
50pub struct Slice {
51    pub inner: Wtf8,
52}
53
54impl fmt::Debug for Slice {
55    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
56        fmt::Debug::fmt(&self.inner, formatter)
57    }
58}
59
60impl fmt::Display for Slice {
61    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
62        fmt::Display::fmt(&self.inner, formatter)
63    }
64}
65
66impl Buf {
67    #[inline]
68    pub fn into_encoded_bytes(self) -> Vec<u8> {
69        self.inner.into_bytes()
70    }
71
72    #[inline]
73    pub unsafe fn from_encoded_bytes_unchecked(s: Vec<u8>) -> Self {
74        unsafe { Self { inner: Wtf8Buf::from_bytes_unchecked(s) } }
75    }
76
77    pub fn with_capacity(capacity: usize) -> Buf {
78        Buf { inner: Wtf8Buf::with_capacity(capacity) }
79    }
80
81    pub fn clear(&mut self) {
82        self.inner.clear()
83    }
84
85    pub fn capacity(&self) -> usize {
86        self.inner.capacity()
87    }
88
89    pub fn from_string(s: String) -> Buf {
90        Buf { inner: Wtf8Buf::from_string(s) }
91    }
92
93    pub fn as_slice(&self) -> &Slice {
94        // SAFETY: Slice is just a wrapper for Wtf8,
95        // and self.inner.as_slice() returns &Wtf8.
96        // Therefore, transmuting &Wtf8 to &Slice is safe.
97        unsafe { mem::transmute(self.inner.as_slice()) }
98    }
99
100    pub fn as_mut_slice(&mut self) -> &mut Slice {
101        // SAFETY: Slice is just a wrapper for Wtf8,
102        // and self.inner.as_mut_slice() returns &mut Wtf8.
103        // Therefore, transmuting &mut Wtf8 to &mut Slice is safe.
104        // Additionally, care should be taken to ensure the slice
105        // is always valid Wtf8.
106        unsafe { mem::transmute(self.inner.as_mut_slice()) }
107    }
108
109    pub fn into_string(self) -> Result<String, Buf> {
110        self.inner.into_string().map_err(|buf| Buf { inner: buf })
111    }
112
113    pub fn push_slice(&mut self, s: &Slice) {
114        self.inner.push_wtf8(&s.inner)
115    }
116
117    pub fn reserve(&mut self, additional: usize) {
118        self.inner.reserve(additional)
119    }
120
121    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
122        self.inner.try_reserve(additional)
123    }
124
125    pub fn reserve_exact(&mut self, additional: usize) {
126        self.inner.reserve_exact(additional)
127    }
128
129    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
130        self.inner.try_reserve_exact(additional)
131    }
132
133    pub fn shrink_to_fit(&mut self) {
134        self.inner.shrink_to_fit()
135    }
136
137    #[inline]
138    pub fn shrink_to(&mut self, min_capacity: usize) {
139        self.inner.shrink_to(min_capacity)
140    }
141
142    #[inline]
143    pub fn leak<'a>(self) -> &'a mut Slice {
144        unsafe { mem::transmute(self.inner.leak()) }
145    }
146
147    #[inline]
148    pub fn into_box(self) -> Box<Slice> {
149        unsafe { mem::transmute(self.inner.into_box()) }
150    }
151
152    #[inline]
153    pub fn from_box(boxed: Box<Slice>) -> Buf {
154        let inner: Box<Wtf8> = unsafe { mem::transmute(boxed) };
155        Buf { inner: Wtf8Buf::from_box(inner) }
156    }
157
158    #[inline]
159    pub fn into_arc(&self) -> Arc<Slice> {
160        self.as_slice().into_arc()
161    }
162
163    #[inline]
164    pub fn into_rc(&self) -> Rc<Slice> {
165        self.as_slice().into_rc()
166    }
167
168    /// Provides plumbing to core `Vec::truncate`.
169    /// More well behaving alternative to allowing outer types
170    /// full mutable access to the core `Vec`.
171    #[inline]
172    pub(crate) fn truncate(&mut self, len: usize) {
173        self.inner.truncate(len);
174    }
175
176    /// Provides plumbing to core `Vec::extend_from_slice`.
177    /// More well behaving alternative to allowing outer types
178    /// full mutable access to the core `Vec`.
179    #[inline]
180    pub(crate) fn extend_from_slice(&mut self, other: &[u8]) {
181        self.inner.extend_from_slice(other);
182    }
183}
184
185impl Slice {
186    #[inline]
187    pub fn as_encoded_bytes(&self) -> &[u8] {
188        self.inner.as_bytes()
189    }
190
191    #[inline]
192    pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice {
193        unsafe { mem::transmute(Wtf8::from_bytes_unchecked(s)) }
194    }
195
196    #[track_caller]
197    pub fn check_public_boundary(&self, index: usize) {
198        check_utf8_boundary(&self.inner, index);
199    }
200
201    #[inline]
202    pub fn from_str(s: &str) -> &Slice {
203        unsafe { mem::transmute(Wtf8::from_str(s)) }
204    }
205
206    pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
207        self.inner.as_str()
208    }
209
210    pub fn to_string_lossy(&self) -> Cow<'_, str> {
211        self.inner.to_string_lossy()
212    }
213
214    pub fn to_owned(&self) -> Buf {
215        Buf { inner: self.inner.to_owned() }
216    }
217
218    pub fn clone_into(&self, buf: &mut Buf) {
219        self.inner.clone_into(&mut buf.inner)
220    }
221
222    #[inline]
223    pub fn into_box(&self) -> Box<Slice> {
224        unsafe { mem::transmute(self.inner.into_box()) }
225    }
226
227    pub fn empty_box() -> Box<Slice> {
228        unsafe { mem::transmute(Wtf8::empty_box()) }
229    }
230
231    #[inline]
232    pub fn into_arc(&self) -> Arc<Slice> {
233        let arc = self.inner.into_arc();
234        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
235    }
236
237    #[inline]
238    pub fn into_rc(&self) -> Rc<Slice> {
239        let rc = self.inner.into_rc();
240        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
241    }
242
243    #[inline]
244    pub fn make_ascii_lowercase(&mut self) {
245        self.inner.make_ascii_lowercase()
246    }
247
248    #[inline]
249    pub fn make_ascii_uppercase(&mut self) {
250        self.inner.make_ascii_uppercase()
251    }
252
253    #[inline]
254    pub fn to_ascii_lowercase(&self) -> Buf {
255        Buf { inner: self.inner.to_ascii_lowercase() }
256    }
257
258    #[inline]
259    pub fn to_ascii_uppercase(&self) -> Buf {
260        Buf { inner: self.inner.to_ascii_uppercase() }
261    }
262
263    #[inline]
264    pub fn is_ascii(&self) -> bool {
265        self.inner.is_ascii()
266    }
267
268    #[inline]
269    pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
270        self.inner.eq_ignore_ascii_case(&other.inner)
271    }
272}
273
274#[unstable(feature = "clone_to_uninit", issue = "126799")]
275unsafe impl CloneToUninit for Slice {
276    #[inline]
277    #[cfg_attr(debug_assertions, track_caller)]
278    unsafe fn clone_to_uninit(&self, dst: *mut u8) {
279        // SAFETY: we're just a transparent wrapper around Wtf8
280        unsafe { self.inner.clone_to_uninit(dst) }
281    }
282}