]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/unix/os_str.rs
Rollup merge of #105955 - Nilstrieb:no-trivial-opt-wrappers-we-have-field-accesses...
[rust.git] / library / std / src / sys / unix / os_str.rs
1 //! The underlying OsString/OsStr implementation on Unix and many other
2 //! systems: just a `Vec<u8>`/`[u8]`.
3
4 use crate::borrow::Cow;
5 use crate::collections::TryReserveError;
6 use crate::fmt;
7 use crate::fmt::Write;
8 use crate::mem;
9 use crate::rc::Rc;
10 use crate::str;
11 use crate::sync::Arc;
12 use crate::sys_common::{AsInner, IntoInner};
13
14 use core::str::Utf8Chunks;
15
16 #[cfg(test)]
17 #[path = "../unix/os_str/tests.rs"]
18 mod tests;
19
20 #[derive(Hash)]
21 #[repr(transparent)]
22 pub struct Buf {
23     pub inner: Vec<u8>,
24 }
25
26 #[repr(transparent)]
27 pub struct Slice {
28     pub inner: [u8],
29 }
30
31 impl fmt::Debug for Slice {
32     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33         fmt::Debug::fmt(&Utf8Chunks::new(&self.inner).debug(), f)
34     }
35 }
36
37 impl fmt::Display for Slice {
38     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39         // If we're the empty string then our iterator won't actually yield
40         // anything, so perform the formatting manually
41         if self.inner.is_empty() {
42             return "".fmt(f);
43         }
44
45         for chunk in Utf8Chunks::new(&self.inner) {
46             let valid = chunk.valid();
47             // If we successfully decoded the whole chunk as a valid string then
48             // we can return a direct formatting of the string which will also
49             // respect various formatting flags if possible.
50             if chunk.invalid().is_empty() {
51                 return valid.fmt(f);
52             }
53
54             f.write_str(valid)?;
55             f.write_char(char::REPLACEMENT_CHARACTER)?;
56         }
57         Ok(())
58     }
59 }
60
61 impl fmt::Debug for Buf {
62     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
63         fmt::Debug::fmt(self.as_slice(), formatter)
64     }
65 }
66
67 impl fmt::Display for Buf {
68     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
69         fmt::Display::fmt(self.as_slice(), formatter)
70     }
71 }
72
73 impl Clone for Buf {
74     #[inline]
75     fn clone(&self) -> Self {
76         Buf { inner: self.inner.clone() }
77     }
78
79     #[inline]
80     fn clone_from(&mut self, source: &Self) {
81         self.inner.clone_from(&source.inner)
82     }
83 }
84
85 impl IntoInner<Vec<u8>> for Buf {
86     fn into_inner(self) -> Vec<u8> {
87         self.inner
88     }
89 }
90
91 impl AsInner<[u8]> for Buf {
92     fn as_inner(&self) -> &[u8] {
93         &self.inner
94     }
95 }
96
97 impl Buf {
98     pub fn from_string(s: String) -> Buf {
99         Buf { inner: s.into_bytes() }
100     }
101
102     #[inline]
103     pub fn with_capacity(capacity: usize) -> Buf {
104         Buf { inner: Vec::with_capacity(capacity) }
105     }
106
107     #[inline]
108     pub fn clear(&mut self) {
109         self.inner.clear()
110     }
111
112     #[inline]
113     pub fn capacity(&self) -> usize {
114         self.inner.capacity()
115     }
116
117     #[inline]
118     pub fn reserve(&mut self, additional: usize) {
119         self.inner.reserve(additional)
120     }
121
122     #[inline]
123     pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
124         self.inner.try_reserve(additional)
125     }
126
127     #[inline]
128     pub fn reserve_exact(&mut self, additional: usize) {
129         self.inner.reserve_exact(additional)
130     }
131
132     #[inline]
133     pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
134         self.inner.try_reserve_exact(additional)
135     }
136
137     #[inline]
138     pub fn shrink_to_fit(&mut self) {
139         self.inner.shrink_to_fit()
140     }
141
142     #[inline]
143     pub fn shrink_to(&mut self, min_capacity: usize) {
144         self.inner.shrink_to(min_capacity)
145     }
146
147     #[inline]
148     pub fn as_slice(&self) -> &Slice {
149         // SAFETY: Slice just wraps [u8],
150         // and &*self.inner is &[u8], therefore
151         // transmuting &[u8] to &Slice is safe.
152         unsafe { mem::transmute(&*self.inner) }
153     }
154
155     #[inline]
156     pub fn as_mut_slice(&mut self) -> &mut Slice {
157         // SAFETY: Slice just wraps [u8],
158         // and &mut *self.inner is &mut [u8], therefore
159         // transmuting &mut [u8] to &mut Slice is safe.
160         unsafe { mem::transmute(&mut *self.inner) }
161     }
162
163     pub fn into_string(self) -> Result<String, Buf> {
164         String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() })
165     }
166
167     pub fn push_slice(&mut self, s: &Slice) {
168         self.inner.extend_from_slice(&s.inner)
169     }
170
171     #[inline]
172     pub fn into_box(self) -> Box<Slice> {
173         unsafe { mem::transmute(self.inner.into_boxed_slice()) }
174     }
175
176     #[inline]
177     pub fn from_box(boxed: Box<Slice>) -> Buf {
178         let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
179         Buf { inner: inner.into_vec() }
180     }
181
182     #[inline]
183     pub fn into_arc(&self) -> Arc<Slice> {
184         self.as_slice().into_arc()
185     }
186
187     #[inline]
188     pub fn into_rc(&self) -> Rc<Slice> {
189         self.as_slice().into_rc()
190     }
191 }
192
193 impl Slice {
194     #[inline]
195     fn from_u8_slice(s: &[u8]) -> &Slice {
196         unsafe { mem::transmute(s) }
197     }
198
199     #[inline]
200     pub fn from_str(s: &str) -> &Slice {
201         Slice::from_u8_slice(s.as_bytes())
202     }
203
204     pub fn to_str(&self) -> Option<&str> {
205         str::from_utf8(&self.inner).ok()
206     }
207
208     pub fn to_string_lossy(&self) -> Cow<'_, str> {
209         String::from_utf8_lossy(&self.inner)
210     }
211
212     pub fn to_owned(&self) -> Buf {
213         Buf { inner: self.inner.to_vec() }
214     }
215
216     pub fn clone_into(&self, buf: &mut Buf) {
217         self.inner.clone_into(&mut buf.inner)
218     }
219
220     #[inline]
221     pub fn into_box(&self) -> Box<Slice> {
222         let boxed: Box<[u8]> = self.inner.into();
223         unsafe { mem::transmute(boxed) }
224     }
225
226     pub fn empty_box() -> Box<Slice> {
227         let boxed: Box<[u8]> = Default::default();
228         unsafe { mem::transmute(boxed) }
229     }
230
231     #[inline]
232     pub fn into_arc(&self) -> Arc<Slice> {
233         let arc: Arc<[u8]> = Arc::from(&self.inner);
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: Rc<[u8]> = Rc::from(&self.inner);
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 }