]> git.lizzy.rs Git - rust.git/blob - src/libstd/ffi/os_str.rs
Auto merge of #30894 - antrik:debug-mpsc, r=brson
[rust.git] / src / libstd / ffi / os_str.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use borrow::{Borrow, Cow, ToOwned};
12 use ffi::CString;
13 use fmt::{self, Debug};
14 use mem;
15 use string::String;
16 use ops;
17 use cmp;
18 use hash::{Hash, Hasher};
19 use vec::Vec;
20
21 use sys::os_str::{Buf, Slice};
22 use sys_common::{AsInner, IntoInner, FromInner};
23
24 /// A type that can represent owned, mutable platform-native strings, but is
25 /// cheaply interconvertable with Rust strings.
26 ///
27 /// The need for this type arises from the fact that:
28 ///
29 /// * On Unix systems, strings are often arbitrary sequences of non-zero
30 ///   bytes, in many cases interpreted as UTF-8.
31 ///
32 /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
33 ///   values, interpreted as UTF-16 when it is valid to do so.
34 ///
35 /// * In Rust, strings are always valid UTF-8, but may contain zeros.
36 ///
37 /// `OsString` and `OsStr` bridge this gap by simultaneously representing Rust
38 /// and platform-native string values, and in particular allowing a Rust string
39 /// to be converted into an "OS" string with no cost.
40 #[derive(Clone)]
41 #[stable(feature = "rust1", since = "1.0.0")]
42 pub struct OsString {
43     inner: Buf
44 }
45
46 /// Slices into OS strings (see `OsString`).
47 #[stable(feature = "rust1", since = "1.0.0")]
48 pub struct OsStr {
49     inner: Slice
50 }
51
52 impl OsString {
53     /// Constructs a new empty `OsString`.
54     #[stable(feature = "rust1", since = "1.0.0")]
55     pub fn new() -> OsString {
56         OsString { inner: Buf::from_string(String::new()) }
57     }
58
59     /// Constructs an `OsString` from a byte sequence.
60     ///
61     /// # Platform behavior
62     ///
63     /// On Unix systems, any byte sequence can be successfully
64     /// converted into an `OsString`.
65     ///
66     /// On Windows system, only UTF-8 byte sequences will successfully
67     /// convert; non UTF-8 data will produce `None`.
68     #[unstable(feature = "convert", reason = "recently added", issue = "27704")]
69     #[rustc_deprecated(reason = "RFC was closed, hides subtle Windows semantics",
70                        since = "1.6.0")]
71     pub fn from_bytes<B>(bytes: B) -> Option<OsString> where B: Into<Vec<u8>> {
72         Self::_from_bytes(bytes.into())
73     }
74
75     #[cfg(unix)]
76     fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
77         use os::unix::ffi::OsStringExt;
78         Some(OsString::from_vec(vec))
79     }
80
81     #[cfg(windows)]
82     fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
83         String::from_utf8(vec).ok().map(OsString::from)
84     }
85
86     /// Converts to an `OsStr` slice.
87     #[stable(feature = "rust1", since = "1.0.0")]
88     pub fn as_os_str(&self) -> &OsStr {
89         self
90     }
91
92     /// Converts the `OsString` into a `String` if it contains valid Unicode data.
93     ///
94     /// On failure, ownership of the original `OsString` is returned.
95     #[stable(feature = "rust1", since = "1.0.0")]
96     pub fn into_string(self) -> Result<String, OsString> {
97         self.inner.into_string().map_err(|buf| OsString { inner: buf} )
98     }
99
100     /// Extends the string with the given `&OsStr` slice.
101     #[stable(feature = "rust1", since = "1.0.0")]
102     pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
103         self.inner.push_slice(&s.as_ref().inner)
104     }
105 }
106
107 #[stable(feature = "rust1", since = "1.0.0")]
108 impl From<String> for OsString {
109     fn from(s: String) -> OsString {
110         OsString { inner: Buf::from_string(s) }
111     }
112 }
113
114 #[stable(feature = "rust1", since = "1.0.0")]
115 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
116     fn from(s: &'a T) -> OsString {
117         s.as_ref().to_os_string()
118     }
119 }
120
121 #[stable(feature = "rust1", since = "1.0.0")]
122 impl ops::Index<ops::RangeFull> for OsString {
123     type Output = OsStr;
124
125     #[inline]
126     fn index(&self, _index: ops::RangeFull) -> &OsStr {
127         OsStr::from_inner(self.inner.as_slice())
128     }
129 }
130
131 #[stable(feature = "rust1", since = "1.0.0")]
132 impl ops::Deref for OsString {
133     type Target = OsStr;
134
135     #[inline]
136     fn deref(&self) -> &OsStr {
137         &self[..]
138     }
139 }
140
141 #[stable(feature = "rust1", since = "1.0.0")]
142 impl Debug for OsString {
143     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
144         fmt::Debug::fmt(&**self, formatter)
145     }
146 }
147
148 #[stable(feature = "rust1", since = "1.0.0")]
149 impl PartialEq for OsString {
150     fn eq(&self, other: &OsString) -> bool {
151         &**self == &**other
152     }
153 }
154
155 #[stable(feature = "rust1", since = "1.0.0")]
156 impl PartialEq<str> for OsString {
157     fn eq(&self, other: &str) -> bool {
158         &**self == other
159     }
160 }
161
162 #[stable(feature = "rust1", since = "1.0.0")]
163 impl PartialEq<OsString> for str {
164     fn eq(&self, other: &OsString) -> bool {
165         &**other == self
166     }
167 }
168
169 #[stable(feature = "rust1", since = "1.0.0")]
170 impl Eq for OsString {}
171
172 #[stable(feature = "rust1", since = "1.0.0")]
173 impl PartialOrd for OsString {
174     #[inline]
175     fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
176         (&**self).partial_cmp(&**other)
177     }
178     #[inline]
179     fn lt(&self, other: &OsString) -> bool { &**self < &**other }
180     #[inline]
181     fn le(&self, other: &OsString) -> bool { &**self <= &**other }
182     #[inline]
183     fn gt(&self, other: &OsString) -> bool { &**self > &**other }
184     #[inline]
185     fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
186 }
187
188 #[stable(feature = "rust1", since = "1.0.0")]
189 impl PartialOrd<str> for OsString {
190     #[inline]
191     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
192         (&**self).partial_cmp(other)
193     }
194 }
195
196 #[stable(feature = "rust1", since = "1.0.0")]
197 impl Ord for OsString {
198     #[inline]
199     fn cmp(&self, other: &OsString) -> cmp::Ordering {
200         (&**self).cmp(&**other)
201     }
202 }
203
204 #[stable(feature = "rust1", since = "1.0.0")]
205 impl Hash for OsString {
206     #[inline]
207     fn hash<H: Hasher>(&self, state: &mut H) {
208         (&**self).hash(state)
209     }
210 }
211
212 impl OsStr {
213     /// Coerces into an `OsStr` slice.
214     #[stable(feature = "rust1", since = "1.0.0")]
215     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
216         s.as_ref()
217     }
218
219     fn from_inner(inner: &Slice) -> &OsStr {
220         unsafe { mem::transmute(inner) }
221     }
222
223     /// Yields a `&str` slice if the `OsStr` is valid unicode.
224     ///
225     /// This conversion may entail doing a check for UTF-8 validity.
226     #[stable(feature = "rust1", since = "1.0.0")]
227     pub fn to_str(&self) -> Option<&str> {
228         self.inner.to_str()
229     }
230
231     /// Converts an `OsStr` to a `Cow<str>`.
232     ///
233     /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
234     #[stable(feature = "rust1", since = "1.0.0")]
235     pub fn to_string_lossy(&self) -> Cow<str> {
236         self.inner.to_string_lossy()
237     }
238
239     /// Copies the slice into an owned `OsString`.
240     #[stable(feature = "rust1", since = "1.0.0")]
241     pub fn to_os_string(&self) -> OsString {
242         OsString { inner: self.inner.to_owned() }
243     }
244
245     /// Yields this `OsStr` as a byte slice.
246     ///
247     /// # Platform behavior
248     ///
249     /// On Unix systems, this is a no-op.
250     ///
251     /// On Windows systems, this returns `None` unless the `OsStr` is
252     /// valid unicode, in which case it produces UTF-8-encoded
253     /// data. This may entail checking validity.
254     #[unstable(feature = "convert", reason = "recently added", issue = "27704")]
255     #[rustc_deprecated(reason = "RFC was closed, hides subtle Windows semantics",
256                        since = "1.6.0")]
257     pub fn to_bytes(&self) -> Option<&[u8]> {
258         if cfg!(windows) {
259             self.to_str().map(|s| s.as_bytes())
260         } else {
261             Some(self.bytes())
262         }
263     }
264
265     /// Creates a `CString` containing this `OsStr` data.
266     ///
267     /// Fails if the `OsStr` contains interior nulls.
268     ///
269     /// This is a convenience for creating a `CString` from
270     /// `self.to_bytes()`, and inherits the platform behavior of the
271     /// `to_bytes` method.
272     #[unstable(feature = "convert", reason = "recently added", issue = "27704")]
273     #[rustc_deprecated(reason = "RFC was closed, hides subtle Windows semantics",
274                        since = "1.6.0")]
275     #[allow(deprecated)]
276     pub fn to_cstring(&self) -> Option<CString> {
277         self.to_bytes().and_then(|b| CString::new(b).ok())
278     }
279
280     /// Gets the underlying byte representation.
281     ///
282     /// Note: it is *crucial* that this API is private, to avoid
283     /// revealing the internal, platform-specific encodings.
284     fn bytes(&self) -> &[u8] {
285         unsafe { mem::transmute(&self.inner) }
286     }
287 }
288
289 #[stable(feature = "rust1", since = "1.0.0")]
290 impl PartialEq for OsStr {
291     fn eq(&self, other: &OsStr) -> bool {
292         self.bytes().eq(other.bytes())
293     }
294 }
295
296 #[stable(feature = "rust1", since = "1.0.0")]
297 impl PartialEq<str> for OsStr {
298     fn eq(&self, other: &str) -> bool {
299         *self == *OsStr::new(other)
300     }
301 }
302
303 #[stable(feature = "rust1", since = "1.0.0")]
304 impl PartialEq<OsStr> for str {
305     fn eq(&self, other: &OsStr) -> bool {
306         *other == *OsStr::new(self)
307     }
308 }
309
310 #[stable(feature = "rust1", since = "1.0.0")]
311 impl Eq for OsStr {}
312
313 #[stable(feature = "rust1", since = "1.0.0")]
314 impl PartialOrd for OsStr {
315     #[inline]
316     fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
317         self.bytes().partial_cmp(other.bytes())
318     }
319     #[inline]
320     fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
321     #[inline]
322     fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
323     #[inline]
324     fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
325     #[inline]
326     fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
327 }
328
329 #[stable(feature = "rust1", since = "1.0.0")]
330 impl PartialOrd<str> for OsStr {
331     #[inline]
332     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
333         self.partial_cmp(OsStr::new(other))
334     }
335 }
336
337 // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
338 // have more flexible coherence rules.
339
340 #[stable(feature = "rust1", since = "1.0.0")]
341 impl Ord for OsStr {
342     #[inline]
343     fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
344 }
345
346 #[stable(feature = "rust1", since = "1.0.0")]
347 impl Hash for OsStr {
348     #[inline]
349     fn hash<H: Hasher>(&self, state: &mut H) {
350         self.bytes().hash(state)
351     }
352 }
353
354 #[stable(feature = "rust1", since = "1.0.0")]
355 impl Debug for OsStr {
356     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
357         self.inner.fmt(formatter)
358     }
359 }
360
361 #[stable(feature = "rust1", since = "1.0.0")]
362 impl Borrow<OsStr> for OsString {
363     fn borrow(&self) -> &OsStr { &self[..] }
364 }
365
366 #[stable(feature = "rust1", since = "1.0.0")]
367 impl ToOwned for OsStr {
368     type Owned = OsString;
369     fn to_owned(&self) -> OsString { self.to_os_string() }
370 }
371
372 #[stable(feature = "rust1", since = "1.0.0")]
373 impl AsRef<OsStr> for OsStr {
374     fn as_ref(&self) -> &OsStr {
375         self
376     }
377 }
378
379 #[stable(feature = "rust1", since = "1.0.0")]
380 impl AsRef<OsStr> for OsString {
381     fn as_ref(&self) -> &OsStr {
382         self
383     }
384 }
385
386 #[stable(feature = "rust1", since = "1.0.0")]
387 impl AsRef<OsStr> for str {
388     fn as_ref(&self) -> &OsStr {
389         OsStr::from_inner(Slice::from_str(self))
390     }
391 }
392
393 #[stable(feature = "rust1", since = "1.0.0")]
394 impl AsRef<OsStr> for String {
395     fn as_ref(&self) -> &OsStr {
396         (&**self).as_ref()
397     }
398 }
399
400 impl FromInner<Buf> for OsString {
401     fn from_inner(buf: Buf) -> OsString {
402         OsString { inner: buf }
403     }
404 }
405
406 impl IntoInner<Buf> for OsString {
407     fn into_inner(self) -> Buf {
408         self.inner
409     }
410 }
411
412 impl AsInner<Slice> for OsStr {
413     fn as_inner(&self) -> &Slice {
414         &self.inner
415     }
416 }