]> git.lizzy.rs Git - rust.git/blob - src/libstd/ffi/os_str.rs
Rollup merge of #34742 - abhijeetbhagat:master, r=steveklabnik
[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 fmt::{self, Debug};
13 use mem;
14 use string::String;
15 use ops;
16 use cmp;
17 use hash::{Hash, Hasher};
18 use vec::Vec;
19
20 use sys::os_str::{Buf, Slice};
21 use sys_common::{AsInner, IntoInner, FromInner};
22
23 /// A type that can represent owned, mutable platform-native strings, but is
24 /// cheaply inter-convertible with Rust strings.
25 ///
26 /// The need for this type arises from the fact that:
27 ///
28 /// * On Unix systems, strings are often arbitrary sequences of non-zero
29 ///   bytes, in many cases interpreted as UTF-8.
30 ///
31 /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
32 ///   values, interpreted as UTF-16 when it is valid to do so.
33 ///
34 /// * In Rust, strings are always valid UTF-8, but may contain zeros.
35 ///
36 /// `OsString` and `OsStr` bridge this gap by simultaneously representing Rust
37 /// and platform-native string values, and in particular allowing a Rust string
38 /// to be converted into an "OS" string with no cost.
39 #[derive(Clone)]
40 #[stable(feature = "rust1", since = "1.0.0")]
41 pub struct OsString {
42     inner: Buf
43 }
44
45 /// Slices into OS strings (see `OsString`).
46 #[stable(feature = "rust1", since = "1.0.0")]
47 pub struct OsStr {
48     inner: Slice
49 }
50
51 impl OsString {
52     /// Constructs a new empty `OsString`.
53     #[stable(feature = "rust1", since = "1.0.0")]
54     pub fn new() -> OsString {
55         OsString { inner: Buf::from_string(String::new()) }
56     }
57
58     #[cfg(unix)]
59     fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
60         use os::unix::ffi::OsStringExt;
61         Some(OsString::from_vec(vec))
62     }
63
64     #[cfg(windows)]
65     fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
66         String::from_utf8(vec).ok().map(OsString::from)
67     }
68
69     /// Converts to an `OsStr` slice.
70     #[stable(feature = "rust1", since = "1.0.0")]
71     pub fn as_os_str(&self) -> &OsStr {
72         self
73     }
74
75     /// Converts the `OsString` into a `String` if it contains valid Unicode data.
76     ///
77     /// On failure, ownership of the original `OsString` is returned.
78     #[stable(feature = "rust1", since = "1.0.0")]
79     pub fn into_string(self) -> Result<String, OsString> {
80         self.inner.into_string().map_err(|buf| OsString { inner: buf} )
81     }
82
83     /// Extends the string with the given `&OsStr` slice.
84     #[stable(feature = "rust1", since = "1.0.0")]
85     pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
86         self.inner.push_slice(&s.as_ref().inner)
87     }
88
89     /// Creates a new `OsString` with the given capacity.
90     ///
91     /// The string will be able to hold exactly `capacity` lenth units of other
92     /// OS strings without reallocating. If `capacity` is 0, the string will not
93     /// allocate.
94     ///
95     /// See main `OsString` documentation information about encoding.
96     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
97     pub fn with_capacity(capacity: usize) -> OsString {
98         OsString {
99             inner: Buf::with_capacity(capacity)
100         }
101     }
102
103     /// Truncates the `OsString` to zero length.
104     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
105     pub fn clear(&mut self) {
106         self.inner.clear()
107     }
108
109     /// Returns the capacity this `OsString` can hold without reallocating.
110     ///
111     /// See `OsString` introduction for information about encoding.
112     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
113     pub fn capacity(&self) -> usize {
114         self.inner.capacity()
115     }
116
117     /// Reserves capacity for at least `additional` more capacity to be inserted
118     /// in the given `OsString`.
119     ///
120     /// The collection may reserve more space to avoid frequent reallocations.
121     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
122     pub fn reserve(&mut self, additional: usize) {
123         self.inner.reserve(additional)
124     }
125
126     /// Reserves the minimum capacity for exactly `additional` more capacity to
127     /// be inserted in the given `OsString`. Does nothing if the capacity is
128     /// already sufficient.
129     ///
130     /// Note that the allocator may give the collection more space than it
131     /// requests. Therefore capacity can not be relied upon to be precisely
132     /// minimal. Prefer reserve if future insertions are expected.
133     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
134     pub fn reserve_exact(&mut self, additional: usize) {
135         self.inner.reserve_exact(additional)
136     }
137 }
138
139 #[stable(feature = "rust1", since = "1.0.0")]
140 impl From<String> for OsString {
141     fn from(s: String) -> OsString {
142         OsString { inner: Buf::from_string(s) }
143     }
144 }
145
146 #[stable(feature = "rust1", since = "1.0.0")]
147 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
148     fn from(s: &'a T) -> OsString {
149         s.as_ref().to_os_string()
150     }
151 }
152
153 #[stable(feature = "rust1", since = "1.0.0")]
154 impl ops::Index<ops::RangeFull> for OsString {
155     type Output = OsStr;
156
157     #[inline]
158     fn index(&self, _index: ops::RangeFull) -> &OsStr {
159         OsStr::from_inner(self.inner.as_slice())
160     }
161 }
162
163 #[stable(feature = "rust1", since = "1.0.0")]
164 impl ops::Deref for OsString {
165     type Target = OsStr;
166
167     #[inline]
168     fn deref(&self) -> &OsStr {
169         &self[..]
170     }
171 }
172
173 #[stable(feature = "osstring_default", since = "1.9.0")]
174 impl Default for OsString {
175     #[inline]
176     fn default() -> OsString {
177         OsString::new()
178     }
179 }
180
181 #[stable(feature = "rust1", since = "1.0.0")]
182 impl Debug for OsString {
183     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
184         fmt::Debug::fmt(&**self, formatter)
185     }
186 }
187
188 #[stable(feature = "rust1", since = "1.0.0")]
189 impl PartialEq for OsString {
190     fn eq(&self, other: &OsString) -> bool {
191         &**self == &**other
192     }
193 }
194
195 #[stable(feature = "rust1", since = "1.0.0")]
196 impl PartialEq<str> for OsString {
197     fn eq(&self, other: &str) -> bool {
198         &**self == other
199     }
200 }
201
202 #[stable(feature = "rust1", since = "1.0.0")]
203 impl PartialEq<OsString> for str {
204     fn eq(&self, other: &OsString) -> bool {
205         &**other == self
206     }
207 }
208
209 #[stable(feature = "rust1", since = "1.0.0")]
210 impl Eq for OsString {}
211
212 #[stable(feature = "rust1", since = "1.0.0")]
213 impl PartialOrd for OsString {
214     #[inline]
215     fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
216         (&**self).partial_cmp(&**other)
217     }
218     #[inline]
219     fn lt(&self, other: &OsString) -> bool { &**self < &**other }
220     #[inline]
221     fn le(&self, other: &OsString) -> bool { &**self <= &**other }
222     #[inline]
223     fn gt(&self, other: &OsString) -> bool { &**self > &**other }
224     #[inline]
225     fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
226 }
227
228 #[stable(feature = "rust1", since = "1.0.0")]
229 impl PartialOrd<str> for OsString {
230     #[inline]
231     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
232         (&**self).partial_cmp(other)
233     }
234 }
235
236 #[stable(feature = "rust1", since = "1.0.0")]
237 impl Ord for OsString {
238     #[inline]
239     fn cmp(&self, other: &OsString) -> cmp::Ordering {
240         (&**self).cmp(&**other)
241     }
242 }
243
244 #[stable(feature = "rust1", since = "1.0.0")]
245 impl Hash for OsString {
246     #[inline]
247     fn hash<H: Hasher>(&self, state: &mut H) {
248         (&**self).hash(state)
249     }
250 }
251
252 impl OsStr {
253     /// Coerces into an `OsStr` slice.
254     #[stable(feature = "rust1", since = "1.0.0")]
255     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
256         s.as_ref()
257     }
258
259     fn from_inner(inner: &Slice) -> &OsStr {
260         unsafe { mem::transmute(inner) }
261     }
262
263     /// Yields a `&str` slice if the `OsStr` is valid Unicode.
264     ///
265     /// This conversion may entail doing a check for UTF-8 validity.
266     #[stable(feature = "rust1", since = "1.0.0")]
267     pub fn to_str(&self) -> Option<&str> {
268         self.inner.to_str()
269     }
270
271     /// Converts an `OsStr` to a `Cow<str>`.
272     ///
273     /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
274     #[stable(feature = "rust1", since = "1.0.0")]
275     pub fn to_string_lossy(&self) -> Cow<str> {
276         self.inner.to_string_lossy()
277     }
278
279     /// Copies the slice into an owned `OsString`.
280     #[stable(feature = "rust1", since = "1.0.0")]
281     pub fn to_os_string(&self) -> OsString {
282         OsString { inner: self.inner.to_owned() }
283     }
284
285     /// Checks whether the `OsStr` is empty.
286     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
287     pub fn is_empty(&self) -> bool {
288         self.inner.inner.is_empty()
289     }
290
291     /// Returns the length of this `OsStr`.
292     ///
293     /// Note that this does **not** return the number of bytes in this string
294     /// as, for example, OS strings on Windows are encoded as a list of `u16`
295     /// rather than a list of bytes. This number is simply useful for passing to
296     /// other methods like `OsString::with_capacity` to avoid reallocations.
297     ///
298     /// See `OsStr` introduction for more information about encoding.
299     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
300     pub fn len(&self) -> usize {
301         self.inner.inner.len()
302     }
303
304     /// Gets the underlying byte representation.
305     ///
306     /// Note: it is *crucial* that this API is private, to avoid
307     /// revealing the internal, platform-specific encodings.
308     fn bytes(&self) -> &[u8] {
309         unsafe { mem::transmute(&self.inner) }
310     }
311 }
312
313 #[stable(feature = "osstring_default", since = "1.9.0")]
314 impl<'a> Default for &'a OsStr {
315     #[inline]
316     fn default() -> &'a OsStr {
317         OsStr::new("")
318     }
319 }
320
321 #[stable(feature = "rust1", since = "1.0.0")]
322 impl PartialEq for OsStr {
323     fn eq(&self, other: &OsStr) -> bool {
324         self.bytes().eq(other.bytes())
325     }
326 }
327
328 #[stable(feature = "rust1", since = "1.0.0")]
329 impl PartialEq<str> for OsStr {
330     fn eq(&self, other: &str) -> bool {
331         *self == *OsStr::new(other)
332     }
333 }
334
335 #[stable(feature = "rust1", since = "1.0.0")]
336 impl PartialEq<OsStr> for str {
337     fn eq(&self, other: &OsStr) -> bool {
338         *other == *OsStr::new(self)
339     }
340 }
341
342 #[stable(feature = "rust1", since = "1.0.0")]
343 impl Eq for OsStr {}
344
345 #[stable(feature = "rust1", since = "1.0.0")]
346 impl PartialOrd for OsStr {
347     #[inline]
348     fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
349         self.bytes().partial_cmp(other.bytes())
350     }
351     #[inline]
352     fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
353     #[inline]
354     fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
355     #[inline]
356     fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
357     #[inline]
358     fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
359 }
360
361 #[stable(feature = "rust1", since = "1.0.0")]
362 impl PartialOrd<str> for OsStr {
363     #[inline]
364     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
365         self.partial_cmp(OsStr::new(other))
366     }
367 }
368
369 // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
370 // have more flexible coherence rules.
371
372 #[stable(feature = "rust1", since = "1.0.0")]
373 impl Ord for OsStr {
374     #[inline]
375     fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
376 }
377
378 macro_rules! impl_cmp {
379     ($lhs:ty, $rhs: ty) => {
380         #[stable(feature = "cmp_os_str", since = "1.8.0")]
381         impl<'a, 'b> PartialEq<$rhs> for $lhs {
382             #[inline]
383             fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
384         }
385
386         #[stable(feature = "cmp_os_str", since = "1.8.0")]
387         impl<'a, 'b> PartialEq<$lhs> for $rhs {
388             #[inline]
389             fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
390         }
391
392         #[stable(feature = "cmp_os_str", since = "1.8.0")]
393         impl<'a, 'b> PartialOrd<$rhs> for $lhs {
394             #[inline]
395             fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
396                 <OsStr as PartialOrd>::partial_cmp(self, other)
397             }
398         }
399
400         #[stable(feature = "cmp_os_str", since = "1.8.0")]
401         impl<'a, 'b> PartialOrd<$lhs> for $rhs {
402             #[inline]
403             fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
404                 <OsStr as PartialOrd>::partial_cmp(self, other)
405             }
406         }
407     }
408 }
409
410 impl_cmp!(OsString, OsStr);
411 impl_cmp!(OsString, &'a OsStr);
412 impl_cmp!(Cow<'a, OsStr>, OsStr);
413 impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
414 impl_cmp!(Cow<'a, OsStr>, OsString);
415
416 #[stable(feature = "rust1", since = "1.0.0")]
417 impl Hash for OsStr {
418     #[inline]
419     fn hash<H: Hasher>(&self, state: &mut H) {
420         self.bytes().hash(state)
421     }
422 }
423
424 #[stable(feature = "rust1", since = "1.0.0")]
425 impl Debug for OsStr {
426     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
427         self.inner.fmt(formatter)
428     }
429 }
430
431 #[stable(feature = "rust1", since = "1.0.0")]
432 impl Borrow<OsStr> for OsString {
433     fn borrow(&self) -> &OsStr { &self[..] }
434 }
435
436 #[stable(feature = "rust1", since = "1.0.0")]
437 impl ToOwned for OsStr {
438     type Owned = OsString;
439     fn to_owned(&self) -> OsString { self.to_os_string() }
440 }
441
442 #[stable(feature = "rust1", since = "1.0.0")]
443 impl AsRef<OsStr> for OsStr {
444     fn as_ref(&self) -> &OsStr {
445         self
446     }
447 }
448
449 #[stable(feature = "rust1", since = "1.0.0")]
450 impl AsRef<OsStr> for OsString {
451     fn as_ref(&self) -> &OsStr {
452         self
453     }
454 }
455
456 #[stable(feature = "rust1", since = "1.0.0")]
457 impl AsRef<OsStr> for str {
458     fn as_ref(&self) -> &OsStr {
459         OsStr::from_inner(Slice::from_str(self))
460     }
461 }
462
463 #[stable(feature = "rust1", since = "1.0.0")]
464 impl AsRef<OsStr> for String {
465     fn as_ref(&self) -> &OsStr {
466         (&**self).as_ref()
467     }
468 }
469
470 impl FromInner<Buf> for OsString {
471     fn from_inner(buf: Buf) -> OsString {
472         OsString { inner: buf }
473     }
474 }
475
476 impl IntoInner<Buf> for OsString {
477     fn into_inner(self) -> Buf {
478         self.inner
479     }
480 }
481
482 impl AsInner<Slice> for OsStr {
483     fn as_inner(&self) -> &Slice {
484         &self.inner
485     }
486 }
487
488 #[cfg(test)]
489 mod tests {
490     use super::*;
491     use sys_common::{AsInner, IntoInner};
492
493     #[test]
494     fn test_os_string_with_capacity() {
495         let os_string = OsString::with_capacity(0);
496         assert_eq!(0, os_string.inner.into_inner().capacity());
497
498         let os_string = OsString::with_capacity(10);
499         assert_eq!(10, os_string.inner.into_inner().capacity());
500
501         let mut os_string = OsString::with_capacity(0);
502         os_string.push("abc");
503         assert!(os_string.inner.into_inner().capacity() >= 3);
504     }
505
506     #[test]
507     fn test_os_string_clear() {
508         let mut os_string = OsString::from("abc");
509         assert_eq!(3, os_string.inner.as_inner().len());
510
511         os_string.clear();
512         assert_eq!(&os_string, "");
513         assert_eq!(0, os_string.inner.as_inner().len());
514     }
515
516     #[test]
517     fn test_os_string_capacity() {
518         let os_string = OsString::with_capacity(0);
519         assert_eq!(0, os_string.capacity());
520
521         let os_string = OsString::with_capacity(10);
522         assert_eq!(10, os_string.capacity());
523
524         let mut os_string = OsString::with_capacity(0);
525         os_string.push("abc");
526         assert!(os_string.capacity() >= 3);
527     }
528
529     #[test]
530     fn test_os_string_reserve() {
531         let mut os_string = OsString::new();
532         assert_eq!(os_string.capacity(), 0);
533
534         os_string.reserve(2);
535         assert!(os_string.capacity() >= 2);
536
537         for _ in 0..16 {
538             os_string.push("a");
539         }
540
541         assert!(os_string.capacity() >= 16);
542         os_string.reserve(16);
543         assert!(os_string.capacity() >= 32);
544
545         os_string.push("a");
546
547         os_string.reserve(16);
548         assert!(os_string.capacity() >= 33)
549     }
550
551     #[test]
552     fn test_os_string_reserve_exact() {
553         let mut os_string = OsString::new();
554         assert_eq!(os_string.capacity(), 0);
555
556         os_string.reserve_exact(2);
557         assert!(os_string.capacity() >= 2);
558
559         for _ in 0..16 {
560             os_string.push("a");
561         }
562
563         assert!(os_string.capacity() >= 16);
564         os_string.reserve_exact(16);
565         assert!(os_string.capacity() >= 32);
566
567         os_string.push("a");
568
569         os_string.reserve_exact(16);
570         assert!(os_string.capacity() >= 33)
571     }
572
573     #[test]
574     fn test_os_string_default() {
575         let os_string: OsString = Default::default();
576         assert_eq!("", &os_string);
577     }
578
579     #[test]
580     fn test_os_str_is_empty() {
581         let mut os_string = OsString::new();
582         assert!(os_string.is_empty());
583
584         os_string.push("abc");
585         assert!(!os_string.is_empty());
586
587         os_string.clear();
588         assert!(os_string.is_empty());
589     }
590
591     #[test]
592     fn test_os_str_len() {
593         let mut os_string = OsString::new();
594         assert_eq!(0, os_string.len());
595
596         os_string.push("abc");
597         assert_eq!(3, os_string.len());
598
599         os_string.clear();
600         assert_eq!(0, os_string.len());
601     }
602
603     #[test]
604     fn test_os_str_default() {
605         let os_str: &OsStr = Default::default();
606         assert_eq!("", os_str);
607     }
608 }