]> git.lizzy.rs Git - rust.git/blob - src/libstd/ffi/os_str.rs
Auto merge of #35871 - bluss:cstring-new, 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 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     ///
255     /// # Examples
256     ///
257     /// ```
258     /// use std::ffi::OsStr;
259     ///
260     /// let os_str = OsStr::new("foo");
261     /// ```
262     #[stable(feature = "rust1", since = "1.0.0")]
263     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
264         s.as_ref()
265     }
266
267     fn from_inner(inner: &Slice) -> &OsStr {
268         unsafe { mem::transmute(inner) }
269     }
270
271     /// Yields a `&str` slice if the `OsStr` is valid Unicode.
272     ///
273     /// This conversion may entail doing a check for UTF-8 validity.
274     #[stable(feature = "rust1", since = "1.0.0")]
275     pub fn to_str(&self) -> Option<&str> {
276         self.inner.to_str()
277     }
278
279     /// Converts an `OsStr` to a `Cow<str>`.
280     ///
281     /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
282     #[stable(feature = "rust1", since = "1.0.0")]
283     pub fn to_string_lossy(&self) -> Cow<str> {
284         self.inner.to_string_lossy()
285     }
286
287     /// Copies the slice into an owned `OsString`.
288     #[stable(feature = "rust1", since = "1.0.0")]
289     pub fn to_os_string(&self) -> OsString {
290         OsString { inner: self.inner.to_owned() }
291     }
292
293     /// Checks whether the `OsStr` is empty.
294     ///
295     /// # Examples
296     ///
297     /// ```
298     /// use std::ffi::OsStr;
299     ///
300     /// let os_str = OsStr::new("");
301     /// assert!(os_str.is_empty());
302     ///
303     /// let os_str = OsStr::new("foo");
304     /// assert!(!os_str.is_empty());
305     /// ```
306     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
307     pub fn is_empty(&self) -> bool {
308         self.inner.inner.is_empty()
309     }
310
311     /// Returns the length of this `OsStr`.
312     ///
313     /// Note that this does **not** return the number of bytes in this string
314     /// as, for example, OS strings on Windows are encoded as a list of `u16`
315     /// rather than a list of bytes. This number is simply useful for passing to
316     /// other methods like `OsString::with_capacity` to avoid reallocations.
317     ///
318     /// See `OsStr` introduction for more information about encoding.
319     ///
320     /// # Examples
321     ///
322     /// ```
323     /// use std::ffi::OsStr;
324     ///
325     /// let os_str = OsStr::new("");
326     /// assert_eq!(os_str.len(), 0);
327     ///
328     /// let os_str = OsStr::new("foo");
329     /// assert_eq!(os_str.len(), 3);
330     /// ```
331     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
332     pub fn len(&self) -> usize {
333         self.inner.inner.len()
334     }
335
336     /// Gets the underlying byte representation.
337     ///
338     /// Note: it is *crucial* that this API is private, to avoid
339     /// revealing the internal, platform-specific encodings.
340     fn bytes(&self) -> &[u8] {
341         unsafe { mem::transmute(&self.inner) }
342     }
343 }
344
345 #[stable(feature = "osstring_default", since = "1.9.0")]
346 impl<'a> Default for &'a OsStr {
347     #[inline]
348     fn default() -> &'a OsStr {
349         OsStr::new("")
350     }
351 }
352
353 #[stable(feature = "rust1", since = "1.0.0")]
354 impl PartialEq for OsStr {
355     fn eq(&self, other: &OsStr) -> bool {
356         self.bytes().eq(other.bytes())
357     }
358 }
359
360 #[stable(feature = "rust1", since = "1.0.0")]
361 impl PartialEq<str> for OsStr {
362     fn eq(&self, other: &str) -> bool {
363         *self == *OsStr::new(other)
364     }
365 }
366
367 #[stable(feature = "rust1", since = "1.0.0")]
368 impl PartialEq<OsStr> for str {
369     fn eq(&self, other: &OsStr) -> bool {
370         *other == *OsStr::new(self)
371     }
372 }
373
374 #[stable(feature = "rust1", since = "1.0.0")]
375 impl Eq for OsStr {}
376
377 #[stable(feature = "rust1", since = "1.0.0")]
378 impl PartialOrd for OsStr {
379     #[inline]
380     fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
381         self.bytes().partial_cmp(other.bytes())
382     }
383     #[inline]
384     fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
385     #[inline]
386     fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
387     #[inline]
388     fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
389     #[inline]
390     fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
391 }
392
393 #[stable(feature = "rust1", since = "1.0.0")]
394 impl PartialOrd<str> for OsStr {
395     #[inline]
396     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
397         self.partial_cmp(OsStr::new(other))
398     }
399 }
400
401 // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
402 // have more flexible coherence rules.
403
404 #[stable(feature = "rust1", since = "1.0.0")]
405 impl Ord for OsStr {
406     #[inline]
407     fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
408 }
409
410 macro_rules! impl_cmp {
411     ($lhs:ty, $rhs: ty) => {
412         #[stable(feature = "cmp_os_str", since = "1.8.0")]
413         impl<'a, 'b> PartialEq<$rhs> for $lhs {
414             #[inline]
415             fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
416         }
417
418         #[stable(feature = "cmp_os_str", since = "1.8.0")]
419         impl<'a, 'b> PartialEq<$lhs> for $rhs {
420             #[inline]
421             fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
422         }
423
424         #[stable(feature = "cmp_os_str", since = "1.8.0")]
425         impl<'a, 'b> PartialOrd<$rhs> for $lhs {
426             #[inline]
427             fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
428                 <OsStr as PartialOrd>::partial_cmp(self, other)
429             }
430         }
431
432         #[stable(feature = "cmp_os_str", since = "1.8.0")]
433         impl<'a, 'b> PartialOrd<$lhs> for $rhs {
434             #[inline]
435             fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
436                 <OsStr as PartialOrd>::partial_cmp(self, other)
437             }
438         }
439     }
440 }
441
442 impl_cmp!(OsString, OsStr);
443 impl_cmp!(OsString, &'a OsStr);
444 impl_cmp!(Cow<'a, OsStr>, OsStr);
445 impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
446 impl_cmp!(Cow<'a, OsStr>, OsString);
447
448 #[stable(feature = "rust1", since = "1.0.0")]
449 impl Hash for OsStr {
450     #[inline]
451     fn hash<H: Hasher>(&self, state: &mut H) {
452         self.bytes().hash(state)
453     }
454 }
455
456 #[stable(feature = "rust1", since = "1.0.0")]
457 impl Debug for OsStr {
458     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
459         self.inner.fmt(formatter)
460     }
461 }
462
463 #[stable(feature = "rust1", since = "1.0.0")]
464 impl Borrow<OsStr> for OsString {
465     fn borrow(&self) -> &OsStr { &self[..] }
466 }
467
468 #[stable(feature = "rust1", since = "1.0.0")]
469 impl ToOwned for OsStr {
470     type Owned = OsString;
471     fn to_owned(&self) -> OsString { self.to_os_string() }
472 }
473
474 #[stable(feature = "rust1", since = "1.0.0")]
475 impl AsRef<OsStr> for OsStr {
476     fn as_ref(&self) -> &OsStr {
477         self
478     }
479 }
480
481 #[stable(feature = "rust1", since = "1.0.0")]
482 impl AsRef<OsStr> for OsString {
483     fn as_ref(&self) -> &OsStr {
484         self
485     }
486 }
487
488 #[stable(feature = "rust1", since = "1.0.0")]
489 impl AsRef<OsStr> for str {
490     fn as_ref(&self) -> &OsStr {
491         OsStr::from_inner(Slice::from_str(self))
492     }
493 }
494
495 #[stable(feature = "rust1", since = "1.0.0")]
496 impl AsRef<OsStr> for String {
497     fn as_ref(&self) -> &OsStr {
498         (&**self).as_ref()
499     }
500 }
501
502 impl FromInner<Buf> for OsString {
503     fn from_inner(buf: Buf) -> OsString {
504         OsString { inner: buf }
505     }
506 }
507
508 impl IntoInner<Buf> for OsString {
509     fn into_inner(self) -> Buf {
510         self.inner
511     }
512 }
513
514 impl AsInner<Slice> for OsStr {
515     fn as_inner(&self) -> &Slice {
516         &self.inner
517     }
518 }
519
520 #[cfg(test)]
521 mod tests {
522     use super::*;
523     use sys_common::{AsInner, IntoInner};
524
525     #[test]
526     fn test_os_string_with_capacity() {
527         let os_string = OsString::with_capacity(0);
528         assert_eq!(0, os_string.inner.into_inner().capacity());
529
530         let os_string = OsString::with_capacity(10);
531         assert_eq!(10, os_string.inner.into_inner().capacity());
532
533         let mut os_string = OsString::with_capacity(0);
534         os_string.push("abc");
535         assert!(os_string.inner.into_inner().capacity() >= 3);
536     }
537
538     #[test]
539     fn test_os_string_clear() {
540         let mut os_string = OsString::from("abc");
541         assert_eq!(3, os_string.inner.as_inner().len());
542
543         os_string.clear();
544         assert_eq!(&os_string, "");
545         assert_eq!(0, os_string.inner.as_inner().len());
546     }
547
548     #[test]
549     fn test_os_string_capacity() {
550         let os_string = OsString::with_capacity(0);
551         assert_eq!(0, os_string.capacity());
552
553         let os_string = OsString::with_capacity(10);
554         assert_eq!(10, os_string.capacity());
555
556         let mut os_string = OsString::with_capacity(0);
557         os_string.push("abc");
558         assert!(os_string.capacity() >= 3);
559     }
560
561     #[test]
562     fn test_os_string_reserve() {
563         let mut os_string = OsString::new();
564         assert_eq!(os_string.capacity(), 0);
565
566         os_string.reserve(2);
567         assert!(os_string.capacity() >= 2);
568
569         for _ in 0..16 {
570             os_string.push("a");
571         }
572
573         assert!(os_string.capacity() >= 16);
574         os_string.reserve(16);
575         assert!(os_string.capacity() >= 32);
576
577         os_string.push("a");
578
579         os_string.reserve(16);
580         assert!(os_string.capacity() >= 33)
581     }
582
583     #[test]
584     fn test_os_string_reserve_exact() {
585         let mut os_string = OsString::new();
586         assert_eq!(os_string.capacity(), 0);
587
588         os_string.reserve_exact(2);
589         assert!(os_string.capacity() >= 2);
590
591         for _ in 0..16 {
592             os_string.push("a");
593         }
594
595         assert!(os_string.capacity() >= 16);
596         os_string.reserve_exact(16);
597         assert!(os_string.capacity() >= 32);
598
599         os_string.push("a");
600
601         os_string.reserve_exact(16);
602         assert!(os_string.capacity() >= 33)
603     }
604
605     #[test]
606     fn test_os_string_default() {
607         let os_string: OsString = Default::default();
608         assert_eq!("", &os_string);
609     }
610
611     #[test]
612     fn test_os_str_is_empty() {
613         let mut os_string = OsString::new();
614         assert!(os_string.is_empty());
615
616         os_string.push("abc");
617         assert!(!os_string.is_empty());
618
619         os_string.clear();
620         assert!(os_string.is_empty());
621     }
622
623     #[test]
624     fn test_os_str_len() {
625         let mut os_string = OsString::new();
626         assert_eq!(0, os_string.len());
627
628         os_string.push("abc");
629         assert_eq!(3, os_string.len());
630
631         os_string.clear();
632         assert_eq!(0, os_string.len());
633     }
634
635     #[test]
636     fn test_os_str_default() {
637         let os_str: &OsStr = Default::default();
638         assert_eq!("", os_str);
639     }
640 }