]> git.proxmox.com Git - rustc.git/blame - src/libstd/ffi/os_str.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / libstd / ffi / os_str.rs
CommitLineData
85aaf69f
SL
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
c34b1796 11use borrow::{Borrow, Cow, ToOwned};
85aaf69f
SL
12use fmt::{self, Debug};
13use mem;
c34b1796 14use string::String;
85aaf69f
SL
15use ops;
16use cmp;
17use hash::{Hash, Hasher};
c34b1796 18use vec::Vec;
85aaf69f
SL
19
20use sys::os_str::{Buf, Slice};
21use sys_common::{AsInner, IntoInner, FromInner};
85aaf69f 22
9cc50fc6 23/// A type that can represent owned, mutable platform-native strings, but is
54a0048b 24/// cheaply inter-convertible with Rust strings.
9cc50fc6
SL
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.
85aaf69f 39#[derive(Clone)]
c34b1796 40#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
41pub struct OsString {
42 inner: Buf
43}
44
9cc50fc6 45/// Slices into OS strings (see `OsString`).
c34b1796 46#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
47pub struct OsStr {
48 inner: Slice
49}
50
51impl OsString {
85aaf69f 52 /// Constructs a new empty `OsString`.
c34b1796 53 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
54 pub fn new() -> OsString {
55 OsString { inner: Buf::from_string(String::new()) }
56 }
57
e9174d1e
SL
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 }
c34b1796 63
e9174d1e
SL
64 #[cfg(windows)]
65 fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
66 String::from_utf8(vec).ok().map(OsString::from)
c34b1796
AL
67 }
68
9346a6ac 69 /// Converts to an `OsStr` slice.
c34b1796
AL
70 #[stable(feature = "rust1", since = "1.0.0")]
71 pub fn as_os_str(&self) -> &OsStr {
72 self
73 }
74
9346a6ac 75 /// Converts the `OsString` into a `String` if it contains valid Unicode data.
85aaf69f
SL
76 ///
77 /// On failure, ownership of the original `OsString` is returned.
c34b1796 78 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
79 pub fn into_string(self) -> Result<String, OsString> {
80 self.inner.into_string().map_err(|buf| OsString { inner: buf} )
81 }
82
9346a6ac 83 /// Extends the string with the given `&OsStr` slice.
c34b1796
AL
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 }
7453a54e 88
54a0048b
SL
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.
7453a54e
SL
94 ///
95 /// See main `OsString` documentation information about encoding.
54a0048b 96 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
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.
54a0048b 104 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
105 pub fn clear(&mut self) {
106 self.inner.clear()
107 }
108
54a0048b 109 /// Returns the capacity this `OsString` can hold without reallocating.
7453a54e
SL
110 ///
111 /// See `OsString` introduction for information about encoding.
54a0048b 112 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
113 pub fn capacity(&self) -> usize {
114 self.inner.capacity()
115 }
116
54a0048b
SL
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")]
7453a54e
SL
122 pub fn reserve(&mut self, additional: usize) {
123 self.inner.reserve(additional)
124 }
125
54a0048b
SL
126 /// Reserves the minimum capacity for exactly `additional` more capacity to
127 /// be inserted in the given `OsString`. Does nothing if the capacity is
7453a54e
SL
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.
54a0048b 133 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
134 pub fn reserve_exact(&mut self, additional: usize) {
135 self.inner.reserve_exact(additional)
136 }
c34b1796
AL
137}
138
139#[stable(feature = "rust1", since = "1.0.0")]
140impl 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")]
147impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
148 fn from(s: &'a T) -> OsString {
149 s.as_ref().to_os_string()
85aaf69f
SL
150 }
151}
152
c34b1796 153#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
154impl ops::Index<ops::RangeFull> for OsString {
155 type Output = OsStr;
156
157 #[inline]
c34b1796 158 fn index(&self, _index: ops::RangeFull) -> &OsStr {
e9174d1e 159 OsStr::from_inner(self.inner.as_slice())
85aaf69f
SL
160 }
161}
162
c34b1796 163#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
164impl ops::Deref for OsString {
165 type Target = OsStr;
166
167 #[inline]
168 fn deref(&self) -> &OsStr {
169 &self[..]
170 }
171}
172
54a0048b
SL
173#[stable(feature = "osstring_default", since = "1.9.0")]
174impl Default for OsString {
175 #[inline]
176 fn default() -> OsString {
177 OsString::new()
178 }
179}
180
c34b1796 181#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
182impl Debug for OsString {
183 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
184 fmt::Debug::fmt(&**self, formatter)
185 }
186}
187
c34b1796 188#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
189impl PartialEq for OsString {
190 fn eq(&self, other: &OsString) -> bool {
191 &**self == &**other
192 }
193}
194
c34b1796 195#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
196impl PartialEq<str> for OsString {
197 fn eq(&self, other: &str) -> bool {
198 &**self == other
199 }
200}
201
c34b1796 202#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
203impl PartialEq<OsString> for str {
204 fn eq(&self, other: &OsString) -> bool {
205 &**other == self
206 }
207}
208
c34b1796 209#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
210impl Eq for OsString {}
211
c34b1796 212#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
213impl 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
c34b1796 228#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
229impl PartialOrd<str> for OsString {
230 #[inline]
231 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
232 (&**self).partial_cmp(other)
233 }
234}
235
c34b1796 236#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
237impl Ord for OsString {
238 #[inline]
239 fn cmp(&self, other: &OsString) -> cmp::Ordering {
240 (&**self).cmp(&**other)
241 }
242}
243
85aaf69f
SL
244#[stable(feature = "rust1", since = "1.0.0")]
245impl Hash for OsString {
246 #[inline]
247 fn hash<H: Hasher>(&self, state: &mut H) {
248 (&**self).hash(state)
249 }
250}
251
252impl OsStr {
9346a6ac 253 /// Coerces into an `OsStr` slice.
c34b1796
AL
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
e9174d1e
SL
259 fn from_inner(inner: &Slice) -> &OsStr {
260 unsafe { mem::transmute(inner) }
261 }
262
54a0048b 263 /// Yields a `&str` slice if the `OsStr` is valid Unicode.
85aaf69f
SL
264 ///
265 /// This conversion may entail doing a check for UTF-8 validity.
c34b1796 266 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
267 pub fn to_str(&self) -> Option<&str> {
268 self.inner.to_str()
269 }
270
9346a6ac 271 /// Converts an `OsStr` to a `Cow<str>`.
85aaf69f
SL
272 ///
273 /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
c34b1796
AL
274 #[stable(feature = "rust1", since = "1.0.0")]
275 pub fn to_string_lossy(&self) -> Cow<str> {
85aaf69f
SL
276 self.inner.to_string_lossy()
277 }
278
9346a6ac 279 /// Copies the slice into an owned `OsString`.
c34b1796 280 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
281 pub fn to_os_string(&self) -> OsString {
282 OsString { inner: self.inner.to_owned() }
283 }
284
7453a54e 285 /// Checks whether the `OsStr` is empty.
54a0048b 286 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
287 pub fn is_empty(&self) -> bool {
288 self.inner.inner.is_empty()
289 }
290
54a0048b
SL
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.
7453a54e 297 ///
54a0048b
SL
298 /// See `OsStr` introduction for more information about encoding.
299 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
300 pub fn len(&self) -> usize {
301 self.inner.inner.len()
302 }
303
9346a6ac 304 /// Gets the underlying byte representation.
85aaf69f
SL
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
54a0048b
SL
313#[stable(feature = "osstring_default", since = "1.9.0")]
314impl<'a> Default for &'a OsStr {
315 #[inline]
316 fn default() -> &'a OsStr {
317 OsStr::new("")
318 }
319}
320
c34b1796 321#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
322impl PartialEq for OsStr {
323 fn eq(&self, other: &OsStr) -> bool {
324 self.bytes().eq(other.bytes())
325 }
326}
327
c34b1796 328#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
329impl PartialEq<str> for OsStr {
330 fn eq(&self, other: &str) -> bool {
c34b1796 331 *self == *OsStr::new(other)
85aaf69f
SL
332 }
333}
334
c34b1796 335#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
336impl PartialEq<OsStr> for str {
337 fn eq(&self, other: &OsStr) -> bool {
c34b1796 338 *other == *OsStr::new(self)
85aaf69f
SL
339 }
340}
341
c34b1796 342#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
343impl Eq for OsStr {}
344
c34b1796 345#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
346impl 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
c34b1796 361#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
362impl PartialOrd<str> for OsStr {
363 #[inline]
364 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
c34b1796 365 self.partial_cmp(OsStr::new(other))
85aaf69f
SL
366 }
367}
368
369// FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
370// have more flexible coherence rules.
371
c34b1796 372#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
373impl Ord for OsStr {
374 #[inline]
375 fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
376}
377
7453a54e
SL
378macro_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
410impl_cmp!(OsString, OsStr);
411impl_cmp!(OsString, &'a OsStr);
412impl_cmp!(Cow<'a, OsStr>, OsStr);
413impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
414impl_cmp!(Cow<'a, OsStr>, OsString);
415
85aaf69f
SL
416#[stable(feature = "rust1", since = "1.0.0")]
417impl Hash for OsStr {
418 #[inline]
419 fn hash<H: Hasher>(&self, state: &mut H) {
420 self.bytes().hash(state)
421 }
422}
423
c34b1796 424#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
425impl Debug for OsStr {
426 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
427 self.inner.fmt(formatter)
428 }
429}
430
c34b1796 431#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
432impl Borrow<OsStr> for OsString {
433 fn borrow(&self) -> &OsStr { &self[..] }
434}
435
c34b1796 436#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
437impl ToOwned for OsStr {
438 type Owned = OsString;
439 fn to_owned(&self) -> OsString { self.to_os_string() }
440}
441
c34b1796
AL
442#[stable(feature = "rust1", since = "1.0.0")]
443impl AsRef<OsStr> for OsStr {
444 fn as_ref(&self) -> &OsStr {
445 self
85aaf69f
SL
446 }
447}
448
c34b1796
AL
449#[stable(feature = "rust1", since = "1.0.0")]
450impl AsRef<OsStr> for OsString {
451 fn as_ref(&self) -> &OsStr {
452 self
453 }
454}
455
456#[stable(feature = "rust1", since = "1.0.0")]
457impl AsRef<OsStr> for str {
458 fn as_ref(&self) -> &OsStr {
e9174d1e 459 OsStr::from_inner(Slice::from_str(self))
c34b1796
AL
460 }
461}
462
463#[stable(feature = "rust1", since = "1.0.0")]
464impl AsRef<OsStr> for String {
465 fn as_ref(&self) -> &OsStr {
e9174d1e 466 (&**self).as_ref()
c34b1796
AL
467 }
468}
469
85aaf69f
SL
470impl FromInner<Buf> for OsString {
471 fn from_inner(buf: Buf) -> OsString {
472 OsString { inner: buf }
473 }
474}
475
476impl IntoInner<Buf> for OsString {
477 fn into_inner(self) -> Buf {
478 self.inner
479 }
480}
481
482impl AsInner<Slice> for OsStr {
483 fn as_inner(&self) -> &Slice {
484 &self.inner
485 }
486}
7453a54e
SL
487
488#[cfg(test)]
489mod 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
54a0048b
SL
573 #[test]
574 fn test_os_string_default() {
575 let os_string: OsString = Default::default();
576 assert_eq!("", &os_string);
577 }
578
7453a54e
SL
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 }
54a0048b
SL
602
603 #[test]
604 fn test_os_str_default() {
605 let os_str: &OsStr = Default::default();
606 assert_eq!("", os_str);
607 }
7453a54e 608}