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