aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/ffi/os_str.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ctr-std/src/ffi/os_str.rs')
-rw-r--r--ctr-std/src/ffi/os_str.rs629
1 files changed, 629 insertions, 0 deletions
diff --git a/ctr-std/src/ffi/os_str.rs b/ctr-std/src/ffi/os_str.rs
new file mode 100644
index 0000000..84b50f0
--- /dev/null
+++ b/ctr-std/src/ffi/os_str.rs
@@ -0,0 +1,629 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use borrow::{Borrow, Cow};
+use fmt::{self, Debug};
+use mem;
+use ops;
+use cmp;
+use hash::{Hash, Hasher};
+
+use sys::os_str::{Buf, Slice};
+use sys_common::{AsInner, IntoInner, FromInner};
+
+/// A type that can represent owned, mutable platform-native strings, but is
+/// cheaply inter-convertible with Rust strings.
+///
+/// The need for this type arises from the fact that:
+///
+/// * On Unix systems, strings are often arbitrary sequences of non-zero
+/// bytes, in many cases interpreted as UTF-8.
+///
+/// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
+/// values, interpreted as UTF-16 when it is valid to do so.
+///
+/// * In Rust, strings are always valid UTF-8, but may contain zeros.
+///
+/// `OsString` and `OsStr` bridge this gap by simultaneously representing Rust
+/// and platform-native string values, and in particular allowing a Rust string
+/// to be converted into an "OS" string with no cost.
+#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct OsString {
+ inner: Buf
+}
+
+/// Slices into OS strings (see `OsString`).
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct OsStr {
+ inner: Slice
+}
+
+impl OsString {
+ /// Constructs a new empty `OsString`.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn new() -> OsString {
+ OsString { inner: Buf::from_string(String::new()) }
+ }
+
+ /// Converts to an `OsStr` slice.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn as_os_str(&self) -> &OsStr {
+ self
+ }
+
+ /// Converts the `OsString` into a `String` if it contains valid Unicode data.
+ ///
+ /// On failure, ownership of the original `OsString` is returned.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn into_string(self) -> Result<String, OsString> {
+ self.inner.into_string().map_err(|buf| OsString { inner: buf} )
+ }
+
+ /// Extends the string with the given `&OsStr` slice.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
+ self.inner.push_slice(&s.as_ref().inner)
+ }
+
+ /// Creates a new `OsString` with the given capacity.
+ ///
+ /// The string will be able to hold exactly `capacity` lenth units of other
+ /// OS strings without reallocating. If `capacity` is 0, the string will not
+ /// allocate.
+ ///
+ /// See main `OsString` documentation information about encoding.
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ pub fn with_capacity(capacity: usize) -> OsString {
+ OsString {
+ inner: Buf::with_capacity(capacity)
+ }
+ }
+
+ /// Truncates the `OsString` to zero length.
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ pub fn clear(&mut self) {
+ self.inner.clear()
+ }
+
+ /// Returns the capacity this `OsString` can hold without reallocating.
+ ///
+ /// See `OsString` introduction for information about encoding.
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ pub fn capacity(&self) -> usize {
+ self.inner.capacity()
+ }
+
+ /// Reserves capacity for at least `additional` more capacity to be inserted
+ /// in the given `OsString`.
+ ///
+ /// The collection may reserve more space to avoid frequent reallocations.
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ pub fn reserve(&mut self, additional: usize) {
+ self.inner.reserve(additional)
+ }
+
+ /// Reserves the minimum capacity for exactly `additional` more capacity to
+ /// be inserted in the given `OsString`. Does nothing if the capacity is
+ /// already sufficient.
+ ///
+ /// Note that the allocator may give the collection more space than it
+ /// requests. Therefore capacity can not be relied upon to be precisely
+ /// minimal. Prefer reserve if future insertions are expected.
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.inner.reserve_exact(additional)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl From<String> for OsString {
+ fn from(s: String) -> OsString {
+ OsString { inner: Buf::from_string(s) }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
+ fn from(s: &'a T) -> OsString {
+ s.as_ref().to_os_string()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ops::Index<ops::RangeFull> for OsString {
+ type Output = OsStr;
+
+ #[inline]
+ fn index(&self, _index: ops::RangeFull) -> &OsStr {
+ OsStr::from_inner(self.inner.as_slice())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ops::Deref for OsString {
+ type Target = OsStr;
+
+ #[inline]
+ fn deref(&self) -> &OsStr {
+ &self[..]
+ }
+}
+
+#[stable(feature = "osstring_default", since = "1.9.0")]
+impl Default for OsString {
+ /// Constructs an empty `OsString`.
+ #[inline]
+ fn default() -> OsString {
+ OsString::new()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Debug for OsString {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ fmt::Debug::fmt(&**self, formatter)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for OsString {
+ fn eq(&self, other: &OsString) -> bool {
+ &**self == &**other
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq<str> for OsString {
+ fn eq(&self, other: &str) -> bool {
+ &**self == other
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq<OsString> for str {
+ fn eq(&self, other: &OsString) -> bool {
+ &**other == self
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Eq for OsString {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for OsString {
+ #[inline]
+ fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
+ (&**self).partial_cmp(&**other)
+ }
+ #[inline]
+ fn lt(&self, other: &OsString) -> bool { &**self < &**other }
+ #[inline]
+ fn le(&self, other: &OsString) -> bool { &**self <= &**other }
+ #[inline]
+ fn gt(&self, other: &OsString) -> bool { &**self > &**other }
+ #[inline]
+ fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd<str> for OsString {
+ #[inline]
+ fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
+ (&**self).partial_cmp(other)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Ord for OsString {
+ #[inline]
+ fn cmp(&self, other: &OsString) -> cmp::Ordering {
+ (&**self).cmp(&**other)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Hash for OsString {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ (&**self).hash(state)
+ }
+}
+
+impl OsStr {
+ /// Coerces into an `OsStr` slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("foo");
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
+ s.as_ref()
+ }
+
+ fn from_inner(inner: &Slice) -> &OsStr {
+ unsafe { mem::transmute(inner) }
+ }
+
+ /// Yields a `&str` slice if the `OsStr` is valid Unicode.
+ ///
+ /// This conversion may entail doing a check for UTF-8 validity.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn to_str(&self) -> Option<&str> {
+ self.inner.to_str()
+ }
+
+ /// Converts an `OsStr` to a `Cow<str>`.
+ ///
+ /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn to_string_lossy(&self) -> Cow<str> {
+ self.inner.to_string_lossy()
+ }
+
+ /// Copies the slice into an owned `OsString`.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn to_os_string(&self) -> OsString {
+ OsString { inner: self.inner.to_owned() }
+ }
+
+ /// Checks whether the `OsStr` is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("");
+ /// assert!(os_str.is_empty());
+ ///
+ /// let os_str = OsStr::new("foo");
+ /// assert!(!os_str.is_empty());
+ /// ```
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ pub fn is_empty(&self) -> bool {
+ self.inner.inner.is_empty()
+ }
+
+ /// Returns the length of this `OsStr`.
+ ///
+ /// Note that this does **not** return the number of bytes in this string
+ /// as, for example, OS strings on Windows are encoded as a list of `u16`
+ /// rather than a list of bytes. This number is simply useful for passing to
+ /// other methods like `OsString::with_capacity` to avoid reallocations.
+ ///
+ /// See `OsStr` introduction for more information about encoding.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("");
+ /// assert_eq!(os_str.len(), 0);
+ ///
+ /// let os_str = OsStr::new("foo");
+ /// assert_eq!(os_str.len(), 3);
+ /// ```
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ pub fn len(&self) -> usize {
+ self.inner.inner.len()
+ }
+
+ /// Gets the underlying byte representation.
+ ///
+ /// Note: it is *crucial* that this API is private, to avoid
+ /// revealing the internal, platform-specific encodings.
+ fn bytes(&self) -> &[u8] {
+ unsafe { mem::transmute(&self.inner) }
+ }
+}
+
+#[stable(feature = "osstring_default", since = "1.9.0")]
+impl<'a> Default for &'a OsStr {
+ /// Creates an empty `OsStr`.
+ #[inline]
+ fn default() -> &'a OsStr {
+ OsStr::new("")
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for OsStr {
+ fn eq(&self, other: &OsStr) -> bool {
+ self.bytes().eq(other.bytes())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq<str> for OsStr {
+ fn eq(&self, other: &str) -> bool {
+ *self == *OsStr::new(other)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq<OsStr> for str {
+ fn eq(&self, other: &OsStr) -> bool {
+ *other == *OsStr::new(self)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Eq for OsStr {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for OsStr {
+ #[inline]
+ fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
+ self.bytes().partial_cmp(other.bytes())
+ }
+ #[inline]
+ fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
+ #[inline]
+ fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
+ #[inline]
+ fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
+ #[inline]
+ fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd<str> for OsStr {
+ #[inline]
+ fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
+ self.partial_cmp(OsStr::new(other))
+ }
+}
+
+// FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
+// have more flexible coherence rules.
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Ord for OsStr {
+ #[inline]
+ fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
+}
+
+macro_rules! impl_cmp {
+ ($lhs:ty, $rhs: ty) => {
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl<'a, 'b> PartialEq<$rhs> for $lhs {
+ #[inline]
+ fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
+ }
+
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl<'a, 'b> PartialEq<$lhs> for $rhs {
+ #[inline]
+ fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
+ }
+
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
+ <OsStr as PartialOrd>::partial_cmp(self, other)
+ }
+ }
+
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
+ <OsStr as PartialOrd>::partial_cmp(self, other)
+ }
+ }
+ }
+}
+
+impl_cmp!(OsString, OsStr);
+impl_cmp!(OsString, &'a OsStr);
+impl_cmp!(Cow<'a, OsStr>, OsStr);
+impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
+impl_cmp!(Cow<'a, OsStr>, OsString);
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Hash for OsStr {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.bytes().hash(state)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Debug for OsStr {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ self.inner.fmt(formatter)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Borrow<OsStr> for OsString {
+ fn borrow(&self) -> &OsStr { &self[..] }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ToOwned for OsStr {
+ type Owned = OsString;
+ fn to_owned(&self) -> OsString { self.to_os_string() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for OsStr {
+ fn as_ref(&self) -> &OsStr {
+ self
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for OsString {
+ fn as_ref(&self) -> &OsStr {
+ self
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for str {
+ fn as_ref(&self) -> &OsStr {
+ OsStr::from_inner(Slice::from_str(self))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for String {
+ fn as_ref(&self) -> &OsStr {
+ (&**self).as_ref()
+ }
+}
+
+impl FromInner<Buf> for OsString {
+ fn from_inner(buf: Buf) -> OsString {
+ OsString { inner: buf }
+ }
+}
+
+impl IntoInner<Buf> for OsString {
+ fn into_inner(self) -> Buf {
+ self.inner
+ }
+}
+
+impl AsInner<Slice> for OsStr {
+ fn as_inner(&self) -> &Slice {
+ &self.inner
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use sys_common::{AsInner, IntoInner};
+
+ #[test]
+ fn test_os_string_with_capacity() {
+ let os_string = OsString::with_capacity(0);
+ assert_eq!(0, os_string.inner.into_inner().capacity());
+
+ let os_string = OsString::with_capacity(10);
+ assert_eq!(10, os_string.inner.into_inner().capacity());
+
+ let mut os_string = OsString::with_capacity(0);
+ os_string.push("abc");
+ assert!(os_string.inner.into_inner().capacity() >= 3);
+ }
+
+ #[test]
+ fn test_os_string_clear() {
+ let mut os_string = OsString::from("abc");
+ assert_eq!(3, os_string.inner.as_inner().len());
+
+ os_string.clear();
+ assert_eq!(&os_string, "");
+ assert_eq!(0, os_string.inner.as_inner().len());
+ }
+
+ #[test]
+ fn test_os_string_capacity() {
+ let os_string = OsString::with_capacity(0);
+ assert_eq!(0, os_string.capacity());
+
+ let os_string = OsString::with_capacity(10);
+ assert_eq!(10, os_string.capacity());
+
+ let mut os_string = OsString::with_capacity(0);
+ os_string.push("abc");
+ assert!(os_string.capacity() >= 3);
+ }
+
+ #[test]
+ fn test_os_string_reserve() {
+ let mut os_string = OsString::new();
+ assert_eq!(os_string.capacity(), 0);
+
+ os_string.reserve(2);
+ assert!(os_string.capacity() >= 2);
+
+ for _ in 0..16 {
+ os_string.push("a");
+ }
+
+ assert!(os_string.capacity() >= 16);
+ os_string.reserve(16);
+ assert!(os_string.capacity() >= 32);
+
+ os_string.push("a");
+
+ os_string.reserve(16);
+ assert!(os_string.capacity() >= 33)
+ }
+
+ #[test]
+ fn test_os_string_reserve_exact() {
+ let mut os_string = OsString::new();
+ assert_eq!(os_string.capacity(), 0);
+
+ os_string.reserve_exact(2);
+ assert!(os_string.capacity() >= 2);
+
+ for _ in 0..16 {
+ os_string.push("a");
+ }
+
+ assert!(os_string.capacity() >= 16);
+ os_string.reserve_exact(16);
+ assert!(os_string.capacity() >= 32);
+
+ os_string.push("a");
+
+ os_string.reserve_exact(16);
+ assert!(os_string.capacity() >= 33)
+ }
+
+ #[test]
+ fn test_os_string_default() {
+ let os_string: OsString = Default::default();
+ assert_eq!("", &os_string);
+ }
+
+ #[test]
+ fn test_os_str_is_empty() {
+ let mut os_string = OsString::new();
+ assert!(os_string.is_empty());
+
+ os_string.push("abc");
+ assert!(!os_string.is_empty());
+
+ os_string.clear();
+ assert!(os_string.is_empty());
+ }
+
+ #[test]
+ fn test_os_str_len() {
+ let mut os_string = OsString::new();
+ assert_eq!(0, os_string.len());
+
+ os_string.push("abc");
+ assert_eq!(3, os_string.len());
+
+ os_string.clear();
+ assert_eq!(0, os_string.len());
+ }
+
+ #[test]
+ fn test_os_str_default() {
+ let os_str: &OsStr = Default::default();
+ assert_eq!("", os_str);
+ }
+}