]> git.lizzy.rs Git - rust.git/blob - src/libstd/ffi/os_str.rs
Auto merge of #30969 - Amanieu:extended_atomic_cmpxchg, 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 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     /// Creates a new `OsString` with the given capacity. The string will be
107     /// able to hold exactly `capacity` bytes without reallocating. If
108     /// `capacity` is 0, the string will not allocate.
109     ///
110     /// See main `OsString` documentation information about encoding.
111     #[unstable(feature = "osstring_simple_functions",
112                reason = "recently added", issue = "29453")]
113     pub fn with_capacity(capacity: usize) -> OsString {
114         OsString {
115             inner: Buf::with_capacity(capacity)
116         }
117     }
118
119     /// Truncates the `OsString` to zero length.
120     #[unstable(feature = "osstring_simple_functions",
121                reason = "recently added", issue = "29453")]
122     pub fn clear(&mut self) {
123         self.inner.clear()
124     }
125
126     /// Returns the number of bytes this `OsString` can hold without
127     /// reallocating.
128     ///
129     /// See `OsString` introduction for information about encoding.
130     #[unstable(feature = "osstring_simple_functions",
131                reason = "recently added", issue = "29453")]
132     pub fn capacity(&self) -> usize {
133         self.inner.capacity()
134     }
135
136     /// Reserves capacity for at least `additional` more bytes to be inserted
137     /// in the given `OsString`. The collection may reserve more space to avoid
138     /// frequent reallocations.
139     #[unstable(feature = "osstring_simple_functions",
140                reason = "recently added", issue = "29453")]
141     pub fn reserve(&mut self, additional: usize) {
142         self.inner.reserve(additional)
143     }
144
145     /// Reserves the minimum capacity for exactly `additional` more bytes to be
146     /// inserted in the given `OsString`. Does nothing if the capacity is
147     /// already sufficient.
148     ///
149     /// Note that the allocator may give the collection more space than it
150     /// requests. Therefore capacity can not be relied upon to be precisely
151     /// minimal. Prefer reserve if future insertions are expected.
152     #[unstable(feature = "osstring_simple_functions",
153                reason = "recently added", issue = "29453")]
154     pub fn reserve_exact(&mut self, additional: usize) {
155         self.inner.reserve_exact(additional)
156     }
157 }
158
159 #[stable(feature = "rust1", since = "1.0.0")]
160 impl From<String> for OsString {
161     fn from(s: String) -> OsString {
162         OsString { inner: Buf::from_string(s) }
163     }
164 }
165
166 #[stable(feature = "rust1", since = "1.0.0")]
167 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
168     fn from(s: &'a T) -> OsString {
169         s.as_ref().to_os_string()
170     }
171 }
172
173 #[stable(feature = "rust1", since = "1.0.0")]
174 impl ops::Index<ops::RangeFull> for OsString {
175     type Output = OsStr;
176
177     #[inline]
178     fn index(&self, _index: ops::RangeFull) -> &OsStr {
179         OsStr::from_inner(self.inner.as_slice())
180     }
181 }
182
183 #[stable(feature = "rust1", since = "1.0.0")]
184 impl ops::Deref for OsString {
185     type Target = OsStr;
186
187     #[inline]
188     fn deref(&self) -> &OsStr {
189         &self[..]
190     }
191 }
192
193 #[stable(feature = "rust1", since = "1.0.0")]
194 impl Debug for OsString {
195     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
196         fmt::Debug::fmt(&**self, formatter)
197     }
198 }
199
200 #[stable(feature = "rust1", since = "1.0.0")]
201 impl PartialEq for OsString {
202     fn eq(&self, other: &OsString) -> bool {
203         &**self == &**other
204     }
205 }
206
207 #[stable(feature = "rust1", since = "1.0.0")]
208 impl PartialEq<str> for OsString {
209     fn eq(&self, other: &str) -> bool {
210         &**self == other
211     }
212 }
213
214 #[stable(feature = "rust1", since = "1.0.0")]
215 impl PartialEq<OsString> for str {
216     fn eq(&self, other: &OsString) -> bool {
217         &**other == self
218     }
219 }
220
221 #[stable(feature = "rust1", since = "1.0.0")]
222 impl Eq for OsString {}
223
224 #[stable(feature = "rust1", since = "1.0.0")]
225 impl PartialOrd for OsString {
226     #[inline]
227     fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
228         (&**self).partial_cmp(&**other)
229     }
230     #[inline]
231     fn lt(&self, other: &OsString) -> bool { &**self < &**other }
232     #[inline]
233     fn le(&self, other: &OsString) -> bool { &**self <= &**other }
234     #[inline]
235     fn gt(&self, other: &OsString) -> bool { &**self > &**other }
236     #[inline]
237     fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
238 }
239
240 #[stable(feature = "rust1", since = "1.0.0")]
241 impl PartialOrd<str> for OsString {
242     #[inline]
243     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
244         (&**self).partial_cmp(other)
245     }
246 }
247
248 #[stable(feature = "rust1", since = "1.0.0")]
249 impl Ord for OsString {
250     #[inline]
251     fn cmp(&self, other: &OsString) -> cmp::Ordering {
252         (&**self).cmp(&**other)
253     }
254 }
255
256 #[stable(feature = "rust1", since = "1.0.0")]
257 impl Hash for OsString {
258     #[inline]
259     fn hash<H: Hasher>(&self, state: &mut H) {
260         (&**self).hash(state)
261     }
262 }
263
264 impl OsStr {
265     /// Coerces into an `OsStr` slice.
266     #[stable(feature = "rust1", since = "1.0.0")]
267     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
268         s.as_ref()
269     }
270
271     fn from_inner(inner: &Slice) -> &OsStr {
272         unsafe { mem::transmute(inner) }
273     }
274
275     /// Yields a `&str` slice if the `OsStr` is valid unicode.
276     ///
277     /// This conversion may entail doing a check for UTF-8 validity.
278     #[stable(feature = "rust1", since = "1.0.0")]
279     pub fn to_str(&self) -> Option<&str> {
280         self.inner.to_str()
281     }
282
283     /// Converts an `OsStr` to a `Cow<str>`.
284     ///
285     /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
286     #[stable(feature = "rust1", since = "1.0.0")]
287     pub fn to_string_lossy(&self) -> Cow<str> {
288         self.inner.to_string_lossy()
289     }
290
291     /// Copies the slice into an owned `OsString`.
292     #[stable(feature = "rust1", since = "1.0.0")]
293     pub fn to_os_string(&self) -> OsString {
294         OsString { inner: self.inner.to_owned() }
295     }
296
297     /// Yields this `OsStr` as a byte slice.
298     ///
299     /// # Platform behavior
300     ///
301     /// On Unix systems, this is a no-op.
302     ///
303     /// On Windows systems, this returns `None` unless the `OsStr` is
304     /// valid unicode, in which case it produces UTF-8-encoded
305     /// data. This may entail checking validity.
306     #[unstable(feature = "convert", reason = "recently added", issue = "27704")]
307     #[rustc_deprecated(reason = "RFC was closed, hides subtle Windows semantics",
308                        since = "1.6.0")]
309     pub fn to_bytes(&self) -> Option<&[u8]> {
310         if cfg!(windows) {
311             self.to_str().map(|s| s.as_bytes())
312         } else {
313             Some(self.bytes())
314         }
315     }
316
317     /// Creates a `CString` containing this `OsStr` data.
318     ///
319     /// Fails if the `OsStr` contains interior nulls.
320     ///
321     /// This is a convenience for creating a `CString` from
322     /// `self.to_bytes()`, and inherits the platform behavior of the
323     /// `to_bytes` method.
324     #[unstable(feature = "convert", reason = "recently added", issue = "27704")]
325     #[rustc_deprecated(reason = "RFC was closed, hides subtle Windows semantics",
326                        since = "1.6.0")]
327     #[allow(deprecated)]
328     pub fn to_cstring(&self) -> Option<CString> {
329         self.to_bytes().and_then(|b| CString::new(b).ok())
330     }
331
332     /// Checks whether the `OsStr` is empty.
333     #[unstable(feature = "osstring_simple_functions",
334                reason = "recently added", issue = "29453")]
335     pub fn is_empty(&self) -> bool {
336         self.inner.inner.is_empty()
337     }
338
339     /// Returns the number of bytes in this `OsStr`.
340     ///
341     /// See `OsStr` introduction for information about encoding.
342     #[unstable(feature = "osstring_simple_functions",
343                reason = "recently added", issue = "29453")]
344     pub fn len(&self) -> usize {
345         self.inner.inner.len()
346     }
347
348     /// Gets the underlying byte representation.
349     ///
350     /// Note: it is *crucial* that this API is private, to avoid
351     /// revealing the internal, platform-specific encodings.
352     fn bytes(&self) -> &[u8] {
353         unsafe { mem::transmute(&self.inner) }
354     }
355 }
356
357 #[stable(feature = "rust1", since = "1.0.0")]
358 impl PartialEq for OsStr {
359     fn eq(&self, other: &OsStr) -> bool {
360         self.bytes().eq(other.bytes())
361     }
362 }
363
364 #[stable(feature = "rust1", since = "1.0.0")]
365 impl PartialEq<str> for OsStr {
366     fn eq(&self, other: &str) -> bool {
367         *self == *OsStr::new(other)
368     }
369 }
370
371 #[stable(feature = "rust1", since = "1.0.0")]
372 impl PartialEq<OsStr> for str {
373     fn eq(&self, other: &OsStr) -> bool {
374         *other == *OsStr::new(self)
375     }
376 }
377
378 #[stable(feature = "rust1", since = "1.0.0")]
379 impl Eq for OsStr {}
380
381 #[stable(feature = "rust1", since = "1.0.0")]
382 impl PartialOrd for OsStr {
383     #[inline]
384     fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
385         self.bytes().partial_cmp(other.bytes())
386     }
387     #[inline]
388     fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
389     #[inline]
390     fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
391     #[inline]
392     fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
393     #[inline]
394     fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
395 }
396
397 #[stable(feature = "rust1", since = "1.0.0")]
398 impl PartialOrd<str> for OsStr {
399     #[inline]
400     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
401         self.partial_cmp(OsStr::new(other))
402     }
403 }
404
405 // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
406 // have more flexible coherence rules.
407
408 #[stable(feature = "rust1", since = "1.0.0")]
409 impl Ord for OsStr {
410     #[inline]
411     fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
412 }
413
414 #[stable(feature = "rust1", since = "1.0.0")]
415 impl Hash for OsStr {
416     #[inline]
417     fn hash<H: Hasher>(&self, state: &mut H) {
418         self.bytes().hash(state)
419     }
420 }
421
422 #[stable(feature = "rust1", since = "1.0.0")]
423 impl Debug for OsStr {
424     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
425         self.inner.fmt(formatter)
426     }
427 }
428
429 #[stable(feature = "rust1", since = "1.0.0")]
430 impl Borrow<OsStr> for OsString {
431     fn borrow(&self) -> &OsStr { &self[..] }
432 }
433
434 #[stable(feature = "rust1", since = "1.0.0")]
435 impl ToOwned for OsStr {
436     type Owned = OsString;
437     fn to_owned(&self) -> OsString { self.to_os_string() }
438 }
439
440 #[stable(feature = "rust1", since = "1.0.0")]
441 impl AsRef<OsStr> for OsStr {
442     fn as_ref(&self) -> &OsStr {
443         self
444     }
445 }
446
447 #[stable(feature = "rust1", since = "1.0.0")]
448 impl AsRef<OsStr> for OsString {
449     fn as_ref(&self) -> &OsStr {
450         self
451     }
452 }
453
454 #[stable(feature = "rust1", since = "1.0.0")]
455 impl AsRef<OsStr> for str {
456     fn as_ref(&self) -> &OsStr {
457         OsStr::from_inner(Slice::from_str(self))
458     }
459 }
460
461 #[stable(feature = "rust1", since = "1.0.0")]
462 impl AsRef<OsStr> for String {
463     fn as_ref(&self) -> &OsStr {
464         (&**self).as_ref()
465     }
466 }
467
468 impl FromInner<Buf> for OsString {
469     fn from_inner(buf: Buf) -> OsString {
470         OsString { inner: buf }
471     }
472 }
473
474 impl IntoInner<Buf> for OsString {
475     fn into_inner(self) -> Buf {
476         self.inner
477     }
478 }
479
480 impl AsInner<Slice> for OsStr {
481     fn as_inner(&self) -> &Slice {
482         &self.inner
483     }
484 }
485
486 #[cfg(test)]
487 mod tests {
488     use super::*;
489     use sys_common::{AsInner, IntoInner};
490
491     #[test]
492     fn test_os_string_with_capacity() {
493         let os_string = OsString::with_capacity(0);
494         assert_eq!(0, os_string.inner.into_inner().capacity());
495
496         let os_string = OsString::with_capacity(10);
497         assert_eq!(10, os_string.inner.into_inner().capacity());
498
499         let mut os_string = OsString::with_capacity(0);
500         os_string.push("abc");
501         assert!(os_string.inner.into_inner().capacity() >= 3);
502     }
503
504     #[test]
505     fn test_os_string_clear() {
506         let mut os_string = OsString::from("abc");
507         assert_eq!(3, os_string.inner.as_inner().len());
508
509         os_string.clear();
510         assert_eq!(&os_string, "");
511         assert_eq!(0, os_string.inner.as_inner().len());
512     }
513
514     #[test]
515     fn test_os_string_capacity() {
516         let os_string = OsString::with_capacity(0);
517         assert_eq!(0, os_string.capacity());
518
519         let os_string = OsString::with_capacity(10);
520         assert_eq!(10, os_string.capacity());
521
522         let mut os_string = OsString::with_capacity(0);
523         os_string.push("abc");
524         assert!(os_string.capacity() >= 3);
525     }
526
527     #[test]
528     fn test_os_string_reserve() {
529         let mut os_string = OsString::new();
530         assert_eq!(os_string.capacity(), 0);
531
532         os_string.reserve(2);
533         assert!(os_string.capacity() >= 2);
534
535         for _ in 0..16 {
536             os_string.push("a");
537         }
538
539         assert!(os_string.capacity() >= 16);
540         os_string.reserve(16);
541         assert!(os_string.capacity() >= 32);
542
543         os_string.push("a");
544
545         os_string.reserve(16);
546         assert!(os_string.capacity() >= 33)
547     }
548
549     #[test]
550     fn test_os_string_reserve_exact() {
551         let mut os_string = OsString::new();
552         assert_eq!(os_string.capacity(), 0);
553
554         os_string.reserve_exact(2);
555         assert!(os_string.capacity() >= 2);
556
557         for _ in 0..16 {
558             os_string.push("a");
559         }
560
561         assert!(os_string.capacity() >= 16);
562         os_string.reserve_exact(16);
563         assert!(os_string.capacity() >= 32);
564
565         os_string.push("a");
566
567         os_string.reserve_exact(16);
568         assert!(os_string.capacity() >= 33)
569     }
570
571     #[test]
572     fn test_os_str_is_empty() {
573         let mut os_string = OsString::new();
574         assert!(os_string.is_empty());
575
576         os_string.push("abc");
577         assert!(!os_string.is_empty());
578
579         os_string.clear();
580         assert!(os_string.is_empty());
581     }
582
583     #[test]
584     fn test_os_str_len() {
585         let mut os_string = OsString::new();
586         assert_eq!(0, os_string.len());
587
588         os_string.push("abc");
589         assert_eq!(3, os_string.len());
590
591         os_string.clear();
592         assert_eq!(0, os_string.len());
593     }
594 }