]> git.lizzy.rs Git - rust.git/blob - src/libstd/ffi/os_str.rs
Auto merge of #23678 - richo:check-flightcheck, r=alexcrichton
[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 //! A type that can represent all platform-native strings, but is cheaply
12 //! interconvertable with Rust strings.
13 //!
14 //! The need for this type arises from the fact that:
15 //!
16 //! * On Unix systems, strings are often arbitrary sequences of non-zero
17 //!   bytes, in many cases interpreted as UTF-8.
18 //!
19 //! * On Windows, strings are often arbitrary sequences of non-zero 16-bit
20 //!   values, interpreted as UTF-16 when it is valid to do so.
21 //!
22 //! * In Rust, strings are always valid UTF-8, but may contain zeros.
23 //!
24 //! The types in this module bridge this gap by simultaneously representing Rust
25 //! and platform-native string values, and in particular allowing a Rust string
26 //! to be converted into an "OS" string with no cost.
27 //!
28 //! **Note**: At the moment, these types are extremely bare-bones, usable only
29 //! for conversion to/from various other string types. Eventually these types
30 //! will offer a full-fledged string API.
31
32 #![unstable(feature = "os",
33             reason = "recently added as part of path/io reform")]
34
35 use core::prelude::*;
36
37 use borrow::{Borrow, Cow, ToOwned};
38 use fmt::{self, Debug};
39 use mem;
40 use string::String;
41 use ops;
42 use cmp;
43 use hash::{Hash, Hasher};
44 use old_path::{Path, GenericPath};
45
46 use sys::os_str::{Buf, Slice};
47 use sys_common::{AsInner, IntoInner, FromInner};
48 use super::AsOsStr;
49
50 /// Owned, mutable OS strings.
51 #[derive(Clone)]
52 #[stable(feature = "rust1", since = "1.0.0")]
53 pub struct OsString {
54     inner: Buf
55 }
56
57 /// Slices into OS strings.
58 #[stable(feature = "rust1", since = "1.0.0")]
59 pub struct OsStr {
60     inner: Slice
61 }
62
63 impl OsString {
64     /// Constructs an `OsString` at no cost by consuming a `String`.
65     #[stable(feature = "rust1", since = "1.0.0")]
66     #[deprecated(since = "1.0.0", reason = "use `from` instead")]
67     pub fn from_string(s: String) -> OsString {
68         OsString::from(s)
69     }
70
71     /// Constructs an `OsString` by copying from a `&str` slice.
72     ///
73     /// Equivalent to: `OsString::from_string(String::from_str(s))`.
74     #[stable(feature = "rust1", since = "1.0.0")]
75     #[deprecated(since = "1.0.0", reason = "use `from` instead")]
76     pub fn from_str(s: &str) -> OsString {
77         OsString::from(s)
78     }
79
80     /// Constructs a new empty `OsString`.
81     #[stable(feature = "rust1", since = "1.0.0")]
82     pub fn new() -> OsString {
83         OsString { inner: Buf::from_string(String::new()) }
84     }
85
86     /// Convert the `OsString` into a `String` if it contains valid Unicode data.
87     ///
88     /// On failure, ownership of the original `OsString` is returned.
89     #[stable(feature = "rust1", since = "1.0.0")]
90     pub fn into_string(self) -> Result<String, OsString> {
91         self.inner.into_string().map_err(|buf| OsString { inner: buf} )
92     }
93
94     /// Extend the string with the given `&OsStr` slice.
95     #[deprecated(since = "1.0.0", reason = "renamed to `push`")]
96     #[unstable(feature = "os")]
97     pub fn push_os_str(&mut self, s: &OsStr) {
98         self.inner.push_slice(&s.inner)
99     }
100
101     /// Extend the string with the given `&OsStr` slice.
102     #[stable(feature = "rust1", since = "1.0.0")]
103     pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
104         self.inner.push_slice(&s.as_ref().inner)
105     }
106 }
107
108 #[stable(feature = "rust1", since = "1.0.0")]
109 impl From<String> for OsString {
110     fn from(s: String) -> OsString {
111         OsString { inner: Buf::from_string(s) }
112     }
113 }
114
115 #[stable(feature = "rust1", since = "1.0.0")]
116 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
117     fn from(s: &'a T) -> OsString {
118         s.as_ref().to_os_string()
119     }
120 }
121
122 #[stable(feature = "rust1", since = "1.0.0")]
123 impl ops::Index<ops::RangeFull> for OsString {
124     type Output = OsStr;
125
126     #[inline]
127     fn index(&self, _index: ops::RangeFull) -> &OsStr {
128         unsafe { mem::transmute(self.inner.as_slice()) }
129     }
130 }
131
132 #[stable(feature = "rust1", since = "1.0.0")]
133 impl ops::Deref for OsString {
134     type Target = OsStr;
135
136     #[inline]
137     fn deref(&self) -> &OsStr {
138         &self[..]
139     }
140 }
141
142 #[stable(feature = "rust1", since = "1.0.0")]
143 impl Debug for OsString {
144     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
145         fmt::Debug::fmt(&**self, formatter)
146     }
147 }
148
149 #[stable(feature = "rust1", since = "1.0.0")]
150 impl PartialEq for OsString {
151     fn eq(&self, other: &OsString) -> bool {
152         &**self == &**other
153     }
154 }
155
156 #[stable(feature = "rust1", since = "1.0.0")]
157 impl PartialEq<str> for OsString {
158     fn eq(&self, other: &str) -> bool {
159         &**self == other
160     }
161 }
162
163 #[stable(feature = "rust1", since = "1.0.0")]
164 impl PartialEq<OsString> for str {
165     fn eq(&self, other: &OsString) -> bool {
166         &**other == self
167     }
168 }
169
170 #[stable(feature = "rust1", since = "1.0.0")]
171 impl Eq for OsString {}
172
173 #[stable(feature = "rust1", since = "1.0.0")]
174 impl PartialOrd for OsString {
175     #[inline]
176     fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
177         (&**self).partial_cmp(&**other)
178     }
179     #[inline]
180     fn lt(&self, other: &OsString) -> bool { &**self < &**other }
181     #[inline]
182     fn le(&self, other: &OsString) -> bool { &**self <= &**other }
183     #[inline]
184     fn gt(&self, other: &OsString) -> bool { &**self > &**other }
185     #[inline]
186     fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
187 }
188
189 #[stable(feature = "rust1", since = "1.0.0")]
190 impl PartialOrd<str> for OsString {
191     #[inline]
192     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
193         (&**self).partial_cmp(other)
194     }
195 }
196
197 #[stable(feature = "rust1", since = "1.0.0")]
198 impl Ord for OsString {
199     #[inline]
200     fn cmp(&self, other: &OsString) -> cmp::Ordering {
201         (&**self).cmp(&**other)
202     }
203 }
204
205 #[stable(feature = "rust1", since = "1.0.0")]
206 impl Hash for OsString {
207     #[inline]
208     fn hash<H: Hasher>(&self, state: &mut H) {
209         (&**self).hash(state)
210     }
211 }
212
213 impl OsStr {
214     /// Coerce directly from a `&str` slice to a `&OsStr` slice.
215     #[stable(feature = "rust1", since = "1.0.0")]
216     pub fn from_str(s: &str) -> &OsStr {
217         unsafe { mem::transmute(Slice::from_str(s)) }
218     }
219
220     /// Yield a `&str` slice if the `OsStr` is valid unicode.
221     ///
222     /// This conversion may entail doing a check for UTF-8 validity.
223     #[stable(feature = "rust1", since = "1.0.0")]
224     pub fn to_str(&self) -> Option<&str> {
225         self.inner.to_str()
226     }
227
228     /// Convert an `OsStr` to a `Cow<str>`.
229     ///
230     /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
231     #[stable(feature = "rust1", since = "1.0.0")]
232     pub fn to_string_lossy(&self) -> Cow<str> {
233         self.inner.to_string_lossy()
234     }
235
236     /// Copy the slice into an owned `OsString`.
237     #[stable(feature = "rust1", since = "1.0.0")]
238     pub fn to_os_string(&self) -> OsString {
239         OsString { inner: self.inner.to_owned() }
240     }
241
242     /// Get the underlying byte representation.
243     ///
244     /// Note: it is *crucial* that this API is private, to avoid
245     /// revealing the internal, platform-specific encodings.
246     fn bytes(&self) -> &[u8] {
247         unsafe { mem::transmute(&self.inner) }
248     }
249 }
250
251 #[stable(feature = "rust1", since = "1.0.0")]
252 impl PartialEq for OsStr {
253     fn eq(&self, other: &OsStr) -> bool {
254         self.bytes().eq(other.bytes())
255     }
256 }
257
258 #[stable(feature = "rust1", since = "1.0.0")]
259 impl PartialEq<str> for OsStr {
260     fn eq(&self, other: &str) -> bool {
261         *self == *OsStr::from_str(other)
262     }
263 }
264
265 #[stable(feature = "rust1", since = "1.0.0")]
266 impl PartialEq<OsStr> for str {
267     fn eq(&self, other: &OsStr) -> bool {
268         *other == *OsStr::from_str(self)
269     }
270 }
271
272 #[stable(feature = "rust1", since = "1.0.0")]
273 impl Eq for OsStr {}
274
275 #[stable(feature = "rust1", since = "1.0.0")]
276 impl PartialOrd for OsStr {
277     #[inline]
278     fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
279         self.bytes().partial_cmp(other.bytes())
280     }
281     #[inline]
282     fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
283     #[inline]
284     fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
285     #[inline]
286     fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
287     #[inline]
288     fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
289 }
290
291 #[stable(feature = "rust1", since = "1.0.0")]
292 impl PartialOrd<str> for OsStr {
293     #[inline]
294     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
295         self.partial_cmp(OsStr::from_str(other))
296     }
297 }
298
299 // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
300 // have more flexible coherence rules.
301
302 #[stable(feature = "rust1", since = "1.0.0")]
303 impl Ord for OsStr {
304     #[inline]
305     fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
306 }
307
308 #[stable(feature = "rust1", since = "1.0.0")]
309 impl Hash for OsStr {
310     #[inline]
311     fn hash<H: Hasher>(&self, state: &mut H) {
312         self.bytes().hash(state)
313     }
314 }
315
316 #[stable(feature = "rust1", since = "1.0.0")]
317 impl Debug for OsStr {
318     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
319         self.inner.fmt(formatter)
320     }
321 }
322
323 #[stable(feature = "rust1", since = "1.0.0")]
324 impl Borrow<OsStr> for OsString {
325     fn borrow(&self) -> &OsStr { &self[..] }
326 }
327
328 #[stable(feature = "rust1", since = "1.0.0")]
329 impl ToOwned for OsStr {
330     type Owned = OsString;
331     fn to_owned(&self) -> OsString { self.to_os_string() }
332 }
333
334 #[stable(feature = "rust1", since = "1.0.0")]
335 #[deprecated(since = "1.0.0", reason = "trait is deprecated")]
336 impl<'a, T: AsOsStr + ?Sized> AsOsStr for &'a T {
337     fn as_os_str(&self) -> &OsStr {
338         (*self).as_os_str()
339     }
340 }
341
342 #[stable(feature = "rust1", since = "1.0.0")]
343 #[deprecated(since = "1.0.0", reason = "trait is deprecated")]
344 impl AsOsStr for OsStr {
345     fn as_os_str(&self) -> &OsStr {
346         self
347     }
348 }
349
350 #[stable(feature = "rust1", since = "1.0.0")]
351 #[deprecated(since = "1.0.0", reason = "trait is deprecated")]
352 impl AsOsStr for OsString {
353     fn as_os_str(&self) -> &OsStr {
354         &self[..]
355     }
356 }
357
358 #[stable(feature = "rust1", since = "1.0.0")]
359 #[deprecated(since = "1.0.0", reason = "trait is deprecated")]
360 impl AsOsStr for str {
361     fn as_os_str(&self) -> &OsStr {
362         OsStr::from_str(self)
363     }
364 }
365
366 #[stable(feature = "rust1", since = "1.0.0")]
367 #[deprecated(since = "1.0.0", reason = "trait is deprecated")]
368 impl AsOsStr for String {
369     fn as_os_str(&self) -> &OsStr {
370         OsStr::from_str(&self[..])
371     }
372 }
373
374 #[stable(feature = "rust1", since = "1.0.0")]
375 impl AsRef<OsStr> for OsStr {
376     fn as_ref(&self) -> &OsStr {
377         self
378     }
379 }
380
381 #[stable(feature = "rust1", since = "1.0.0")]
382 impl AsRef<OsStr> for OsString {
383     fn as_ref(&self) -> &OsStr {
384         self
385     }
386 }
387
388 #[stable(feature = "rust1", since = "1.0.0")]
389 impl AsRef<OsStr> for str {
390     fn as_ref(&self) -> &OsStr {
391         OsStr::from_str(self)
392     }
393 }
394
395 #[stable(feature = "rust1", since = "1.0.0")]
396 impl AsRef<OsStr> for String {
397     fn as_ref(&self) -> &OsStr {
398         OsStr::from_str(&self[..])
399     }
400 }
401
402 #[allow(deprecated)]
403 #[stable(feature = "rust1", since = "1.0.0")]
404 #[deprecated(since = "1.0.0", reason = "trait is deprecated")]
405 impl AsOsStr for Path {
406     #[cfg(unix)]
407     fn as_os_str(&self) -> &OsStr {
408         unsafe { mem::transmute(self.as_vec()) }
409     }
410     #[cfg(windows)]
411     fn as_os_str(&self) -> &OsStr {
412         // currently .as_str() is actually infallible on windows
413         OsStr::from_str(self.as_str().unwrap())
414     }
415 }
416
417 impl FromInner<Buf> for OsString {
418     fn from_inner(buf: Buf) -> OsString {
419         OsString { inner: buf }
420     }
421 }
422
423 impl IntoInner<Buf> for OsString {
424     fn into_inner(self) -> Buf {
425         self.inner
426     }
427 }
428
429 impl AsInner<Slice> for OsStr {
430     fn as_inner(&self) -> &Slice {
431         &self.inner
432     }
433 }