diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 97bf33335b02a..add76cce8f8ce 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -41,6 +41,7 @@ use mem; use string::String; use ops; use cmp; +use str; use hash::{Hash, Hasher}; use vec::Vec; @@ -76,8 +77,23 @@ impl OsString { /// /// On Windows system, only UTF-8 byte sequences will successfully /// convert; non UTF-8 data will produce `None`. + #[deprecated(reason = "Renamed to from_platform_bytes", since = "1.2.0")] #[unstable(feature = "convert", reason = "recently added")] pub fn from_bytes(bytes: B) -> Option where B: Into> { + OsString::from_platform_bytes(bytes) + } + + /// Constructs an `OsString` from a byte sequence. + /// + /// # Platform behavior + /// + /// On Unix systems, any byte sequence can be successfully + /// converted into an `OsString`. + /// + /// On Windows system, only UTF-8 byte sequences will successfully + /// convert; non UTF-8 data will produce `None`. + #[unstable(feature = "convert", reason = "recently added")] + pub fn from_platform_bytes(bytes: B) -> Option where B: Into> { #[cfg(unix)] fn from_bytes_inner(vec: Vec) -> Option { use os::unix::ffi::OsStringExt; @@ -265,6 +281,24 @@ impl OsStr { } } + /// Converts a byte slice to an `OsStr` slice. + /// + /// # Platform behavior + /// + /// On Unix systems, this is a no-op. + /// + /// On Windows systems, only UTF-8 byte sequences will successfully + /// convert; non UTF-8 data will produce `None`. + #[unstable(feature = "convert", reason = "recently added")] + pub fn from_platform_bytes(bytes: &[u8]) -> Option<&OsStr> { + if cfg!(windows) { + str::from_utf8(bytes).ok().map(|s| s.as_ref()) + } else { + use os::unix::ffi::OsStrExt; + Some(::from_bytes(bytes)) + } + } + /// Creates a `CString` containing this `OsStr` data. /// /// Fails if the `OsStr` contains interior nulls. diff --git a/src/test/run-pass/osstr_conversions.rs b/src/test/run-pass/osstr_conversions.rs new file mode 100644 index 0000000000000..d7ba15e716122 --- /dev/null +++ b/src/test/run-pass/osstr_conversions.rs @@ -0,0 +1,49 @@ +// Copyright 2012-2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(convert)] + +use std::ffi::{OsStr, OsString}; + +fn main() { + // Valid UTF-8 + let vec1: Vec = b"t\xC3\xA9st".to_vec(); + let oso1: OsString = OsString::from_platform_bytes(vec1).unwrap(); + assert!(oso1.to_bytes() == Some(b"t\xC3\xA9st")); + assert!(oso1.to_str() == Some("t\u{E9}st")); + // Not UTF-8 + let vec2: Vec = b"t\xE9st".to_vec(); + let oso2: OsString = OsString::from_platform_bytes(vec2).unwrap(); + if cfg!(windows) { + assert!(oso2.to_bytes() == None); + } else { + assert!(oso2.to_bytes() == Some(b"t\xE9st")); + } + assert_eq!(oso2.to_str(), None); + + // Valid UTF-8 + let by1: &[u8] = b"t\xC3\xA9st"; + let oss1: &OsStr = OsStr::from_platform_bytes(by1).unwrap(); + assert_eq!(oss1.to_bytes().unwrap().as_ptr(), by1.as_ptr()); + assert_eq!(oss1.to_str().unwrap().as_ptr(), by1.as_ptr()); + // Not UTF-8 + let by2: &[u8] = b"t\xE9st"; + let oss2: &OsStr = OsStr::from_platform_bytes(by2).unwrap(); + if cfg!(windows) { + assert_eq!(oss2.to_bytes(), None); + } else { + assert_eq!(oss2.to_bytes().unwrap().as_ptr(), by2.as_ptr()); + } + assert_eq!(oss2.to_str(), None); + + if cfg!(windows) { + // FIXME: needs valid-windows-utf16-invalid-unicode test cases + } +}