From c5369ebc7f4791c4e291951751b8964052c7a523 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Wed, 21 Jan 2015 15:55:31 -0800 Subject: Add ffi::OsString and OsStr Per [RFC 517](https://github.com/rust-lang/rfcs/pull/575/), this commit introduces platform-native strings. The API is essentially as described in the RFC. The WTF-8 implementation is adapted from @SimonSapin's [implementation](https://github.com/SimonSapin/rust-wtf8). To make this work, some encodign and decoding functionality in `libcore` is now exported in a "raw" fashion reusable for WTF-8. These exports are *not* reexported in `std`, nor are they stable. --- src/libstd/sys/windows/ext.rs | 34 ++++++++++++++++- src/libstd/sys/windows/mod.rs | 1 + src/libstd/sys/windows/os_str.rs | 82 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 src/libstd/sys/windows/os_str.rs (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index 87ff31ab73c..de37c428288 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -16,7 +16,11 @@ #![unstable] -use sys_common::AsInner; +pub use sys_common::wtf8::{Wtf8Buf, EncodeWide}; + +use sys::os_str::Buf; +use sys_common::{AsInner, FromInner}; +use ffi::{OsStr, OsString}; use libc; use io; @@ -92,9 +96,35 @@ impl AsRawSocket for io::net::udp::UdpSocket { } } +// Windows-specific extensions to `OsString`. +pub trait OsStringExt { + /// Create an `OsString` from a potentially ill-formed UTF-16 slice of 16-bit code units. + /// + /// This is lossless: calling `.encode_wide()` on the resulting string + /// will always return the original code units. + fn from_wide(wide: &[u16]) -> Self; +} + +impl OsStringExt for OsString { + fn from_wide(wide: &[u16]) -> OsString { + FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) }) + } +} + +// Windows-specific extensions to `OsStr`. +pub trait OsStrExt { + fn encode_wide(&self) -> EncodeWide; +} + +impl OsStrExt for OsStr { + fn encode_wide(&self) -> EncodeWide { + self.as_inner().inner.encode_wide() + } +} + /// A prelude for conveniently writing platform-specific code. /// /// Includes all extension traits, and some important type definitions. pub mod prelude { - pub use super::{Socket, Handle, AsRawSocket, AsRawHandle}; + pub use super::{Socket, Handle, AsRawSocket, AsRawHandle, OsStrExt, OsStringExt}; } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 72fc2f8700d..876159623ac 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -44,6 +44,7 @@ pub mod fs; pub mod helper_signal; pub mod mutex; pub mod os; +pub mod os_str; pub mod pipe; pub mod process; pub mod rwlock; diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs new file mode 100644 index 00000000000..aab2406cef9 --- /dev/null +++ b/src/libstd/sys/windows/os_str.rs @@ -0,0 +1,82 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// The underlying OsString/OsStr implementation on Windows is a +/// wrapper around the "WTF-8" encoding; see the `wtf8` module for more. + +use fmt::{self, Debug}; +use sys_common::wtf8::{Wtf8, Wtf8Buf}; +use string::{String, CowString}; +use result::Result; +use option::Option; +use mem; + +#[derive(Clone)] +pub struct Buf { + pub inner: Wtf8Buf +} + +impl Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + self.as_slice().fmt(formatter) + } +} + +pub struct Slice { + pub inner: Wtf8 +} + +impl Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + self.inner.fmt(formatter) + } +} + +impl Buf { + pub fn from_string(s: String) -> Buf { + Buf { inner: Wtf8Buf::from_string(s) } + } + + pub fn from_str(s: &str) -> Buf { + Buf { inner: Wtf8Buf::from_str(s) } + } + + pub fn as_slice(&self) -> &Slice { + unsafe { mem::transmute(self.inner.as_slice()) } + } + + pub fn into_string(self) -> Result { + self.inner.into_string().map_err(|buf| Buf { inner: buf }) + } + + pub fn push_slice(&mut self, s: &Slice) { + self.inner.push_wtf8(&s.inner) + } +} + +impl Slice { + pub fn from_str(s: &str) -> &Slice { + unsafe { mem::transmute(Wtf8::from_str(s)) } + } + + pub fn to_str(&self) -> Option<&str> { + self.inner.as_str() + } + + pub fn to_string_lossy(&self) -> CowString { + self.inner.to_string_lossy() + } + + pub fn to_owned(&self) -> Buf { + let mut buf = Wtf8Buf::with_capacity(self.inner.len()); + buf.push_wtf8(&self.inner); + Buf { inner: buf } + } +} -- cgit 1.4.1-3-g733a5