diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index de0ca4971f5c2..977b7dc32c565 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -292,6 +292,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts { save_metrics: config.save_metrics.clone(), test_shard: config.test_shard.clone(), nocapture: false, + color: test::AutoColor, } } diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index a48a9f1be7541..8fa34dd6d27c9 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -11,7 +11,7 @@ use std::os; use std::str; use std::io::process::{ProcessExit, Command, Process, ProcessOutput}; -use std::unstable::dynamic_lib::DynamicLibrary; +use std::dynamic_lib::DynamicLibrary; fn target_env(lib_path: &str, prog: &str) -> Vec<(String, String)> { let prog = if cfg!(windows) {prog.slice_to(prog.len() - 4)} else {prog}; diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs index 42c8177977057..e100baa1e3ac4 100644 --- a/src/libcollections/bitv.rs +++ b/src/libcollections/bitv.rs @@ -13,6 +13,7 @@ use core::prelude::*; use core::cmp; +use core::default::Default; use core::fmt; use core::iter::{Enumerate, Repeat, Map, Zip}; use core::ops; @@ -698,6 +699,11 @@ pub struct BitvSet { bitv: BigBitv } +impl Default for BitvSet { + #[inline] + fn default() -> BitvSet { BitvSet::new() } +} + impl BitvSet { /// Creates a new bit vector set with initially no contents pub fn new() -> BitvSet { diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 5a23124569138..ac8c5c5557ed9 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -24,6 +24,7 @@ use core::prelude::*; use alloc::owned::Box; +use core::default::Default; use core::fmt; use core::iter; use core::mem; @@ -262,6 +263,11 @@ impl Deque for DList { } } +impl Default for DList { + #[inline] + fn default() -> DList { DList::new() } +} + impl DList { /// Create an empty DList #[inline] diff --git a/src/libcollections/priority_queue.rs b/src/libcollections/priority_queue.rs index ea3e7d1747170..f25864933f2eb 100644 --- a/src/libcollections/priority_queue.rs +++ b/src/libcollections/priority_queue.rs @@ -14,6 +14,7 @@ use core::prelude::*; +use core::default::Default; use core::mem::{zeroed, replace, swap}; use core::ptr; @@ -37,6 +38,11 @@ impl Mutable for PriorityQueue { fn clear(&mut self) { self.data.truncate(0) } } +impl Default for PriorityQueue { + #[inline] + fn default() -> PriorityQueue { PriorityQueue::new() } +} + impl PriorityQueue { /// An iterator visiting all values in underlying vector, in /// arbitrary order. diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ringbuf.rs index addf73d67a88e..ae1925126cae7 100644 --- a/src/libcollections/ringbuf.rs +++ b/src/libcollections/ringbuf.rs @@ -16,6 +16,7 @@ use core::prelude::*; use core::cmp; +use core::default::Default; use core::fmt; use core::iter::RandomAccessIterator; @@ -112,6 +113,11 @@ impl Deque for RingBuf { } } +impl Default for RingBuf { + #[inline] + fn default() -> RingBuf { RingBuf::new() } +} + impl RingBuf { /// Create an empty RingBuf pub fn new() -> RingBuf { diff --git a/src/libcollections/smallintmap.rs b/src/libcollections/smallintmap.rs index cc901864ab532..6b4982de08216 100644 --- a/src/libcollections/smallintmap.rs +++ b/src/libcollections/smallintmap.rs @@ -17,6 +17,7 @@ use core::prelude::*; +use core::default::Default; use core::fmt; use core::iter::{Enumerate, FilterMap}; use core::mem::replace; @@ -114,6 +115,11 @@ impl MutableMap for SmallIntMap { } } +impl Default for SmallIntMap { + #[inline] + fn default() -> SmallIntMap { SmallIntMap::new() } +} + impl SmallIntMap { /// Create an empty SmallIntMap pub fn new() -> SmallIntMap { SmallIntMap{v: vec!()} } diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 489fe60cebf0e..1f4ee52008cdc 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -15,6 +15,7 @@ use core::prelude::*; use alloc::owned::Box; +use core::default::Default; use core::fmt; use core::fmt::Show; use core::iter::Peekable; @@ -135,6 +136,11 @@ impl MutableMap for TreeMap { } } +impl Default for TreeMap { + #[inline] + fn default() -> TreeMap { TreeMap::new() } +} + impl TreeMap { /// Create an empty TreeMap pub fn new() -> TreeMap { TreeMap{root: None, length: 0} } @@ -633,6 +639,11 @@ impl MutableSet for TreeSet { fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } } +impl Default for TreeSet { + #[inline] + fn default() -> TreeSet { TreeSet::new() } +} + impl TreeSet { /// Create an empty TreeSet #[inline] diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs index 6e99d6054a564..3f4fdd66b802a 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie.rs @@ -13,6 +13,7 @@ use core::prelude::*; use alloc::owned::Box; +use core::default::Default; use core::mem::zeroed; use core::mem; use core::uint; @@ -105,6 +106,11 @@ impl MutableMap for TrieMap { } } +impl Default for TrieMap { + #[inline] + fn default() -> TrieMap { TrieMap::new() } +} + impl TrieMap { /// Create an empty TrieMap #[inline] @@ -332,6 +338,11 @@ impl MutableSet for TrieSet { } } +impl Default for TrieSet { + #[inline] + fn default() -> TrieSet { TrieSet::new() } +} + impl TrieSet { /// Create an empty TrieSet #[inline] diff --git a/src/libnative/io/c_win32.rs b/src/libnative/io/c_win32.rs index 93b3ec7ccefbf..1ec25933eec3c 100644 --- a/src/libnative/io/c_win32.rs +++ b/src/libnative/io/c_win32.rs @@ -69,7 +69,6 @@ extern "system" { pub mod compat { use std::intrinsics::{atomic_store_relaxed, transmute}; use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; - use std::os::win32::as_utf16_p; extern "system" { fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; @@ -80,12 +79,11 @@ pub mod compat { // This way, calling a function in this compatibility layer (after it's loaded) shouldn't // be any slower than a regular DLL call. unsafe fn store_func(ptr: *mut T, module: &str, symbol: &str, fallback: T) { - as_utf16_p(module, |module| { - symbol.with_c_str(|symbol| { - let handle = GetModuleHandleW(module); - let func: Option = transmute(GetProcAddress(handle, symbol)); - atomic_store_relaxed(ptr, func.unwrap_or(fallback)) - }) + let module = module.to_utf16().append_one(0); + symbol.with_c_str(|symbol| { + let handle = GetModuleHandleW(module.as_ptr()); + let func: Option = transmute(GetProcAddress(handle, symbol)); + atomic_store_relaxed(ptr, func.unwrap_or(fallback)) }) } diff --git a/src/libnative/io/file_win32.rs b/src/libnative/io/file_win32.rs index 2a5b78e55067c..5ace8e347c67e 100644 --- a/src/libnative/io/file_win32.rs +++ b/src/libnative/io/file_win32.rs @@ -15,10 +15,10 @@ use libc::{c_int, c_void}; use libc; use std::c_str::CString; use std::mem; -use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode}; +use std::os::win32::fill_utf16_buf_and_decode; use std::ptr; use std::rt::rtio; -use std::rt::rtio::IoResult; +use std::rt::rtio::{IoResult, IoError}; use std::str; use std::vec; @@ -253,6 +253,17 @@ impl Drop for Inner { } } +pub fn to_utf16(s: &CString) -> IoResult> { + match s.as_str() { + Some(s) => Ok(s.to_utf16().append_one(0)), + None => Err(IoError { + code: libc::ERROR_INVALID_NAME as uint, + extra: 0, + detail: Some("valid unicode input required".to_str()), + }) + } +} + pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess) -> IoResult { // Flags passed to open_osfhandle @@ -299,15 +310,16 @@ pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess) // Compat with unix, this allows opening directories (see libuv) dwFlagsAndAttributes |= libc::FILE_FLAG_BACKUP_SEMANTICS; - let handle = as_utf16_p(path.as_str().unwrap(), |buf| unsafe { - libc::CreateFileW(buf, + let path = try!(to_utf16(path)); + let handle = unsafe { + libc::CreateFileW(path.as_ptr(), dwDesiredAccess, dwShareMode, ptr::mut_null(), dwCreationDisposition, dwFlagsAndAttributes, ptr::mut_null()) - }); + }; if handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE { Err(super::last_error()) } else { @@ -324,11 +336,10 @@ pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess) } pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> { + let p = try!(to_utf16(p)); super::mkerr_winbool(unsafe { // FIXME: turn mode into something useful? #2623 - as_utf16_p(p.as_str().unwrap(), |buf| { - libc::CreateDirectoryW(buf, ptr::mut_null()) - }) + libc::CreateDirectoryW(p.as_ptr(), ptr::mut_null()) }) } @@ -351,9 +362,11 @@ pub fn readdir(p: &CString) -> IoResult> { let star = Path::new(unsafe { CString::new(p.with_ref(|p| p), false) }).join("*"); - as_utf16_p(star.as_str().unwrap(), |path_ptr| unsafe { + let path = try!(to_utf16(&star.to_c_str())); + + unsafe { let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint); - let find_handle = libc::FindFirstFileW(path_ptr, wfd_ptr as libc::HANDLE); + let find_handle = libc::FindFirstFileW(path.as_ptr(), wfd_ptr as libc::HANDLE); if find_handle as libc::c_int != libc::INVALID_HANDLE_VALUE { let mut paths = vec!(); let mut more_files = 1 as libc::c_int; @@ -377,37 +390,35 @@ pub fn readdir(p: &CString) -> IoResult> { } else { Err(super::last_error()) } - }) + } } pub fn unlink(p: &CString) -> IoResult<()> { + let p = try!(to_utf16(p)); super::mkerr_winbool(unsafe { - as_utf16_p(p.as_str().unwrap(), |buf| { - libc::DeleteFileW(buf) - }) + libc::DeleteFileW(p.as_ptr()) }) } pub fn rename(old: &CString, new: &CString) -> IoResult<()> { + let old = try!(to_utf16(old)); + let new = try!(to_utf16(new)); super::mkerr_winbool(unsafe { - as_utf16_p(old.as_str().unwrap(), |old| { - as_utf16_p(new.as_str().unwrap(), |new| { - libc::MoveFileExW(old, new, libc::MOVEFILE_REPLACE_EXISTING) - }) - }) + libc::MoveFileExW(old.as_ptr(), new.as_ptr(), + libc::MOVEFILE_REPLACE_EXISTING) }) } pub fn chmod(p: &CString, mode: uint) -> IoResult<()> { - super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe { - libc::wchmod(p, mode as libc::c_int) - })) + let p = try!(to_utf16(p)); + super::mkerr_libc(unsafe { + libc::wchmod(p.as_ptr(), mode as libc::c_int) + }) } pub fn rmdir(p: &CString) -> IoResult<()> { - super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe { - libc::wrmdir(p) - })) + let p = try!(to_utf16(p)); + super::mkerr_libc(unsafe { libc::wrmdir(p.as_ptr()) }) } pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> { @@ -418,16 +429,15 @@ pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> { pub fn readlink(p: &CString) -> IoResult { // FIXME: I have a feeling that this reads intermediate symlinks as well. use io::c::compat::kernel32::GetFinalPathNameByHandleW; + let p = try!(to_utf16(p)); let handle = unsafe { - as_utf16_p(p.as_str().unwrap(), |p| { - libc::CreateFileW(p, - libc::GENERIC_READ, - libc::FILE_SHARE_READ, - ptr::mut_null(), - libc::OPEN_EXISTING, - libc::FILE_ATTRIBUTE_NORMAL, - ptr::mut_null()) - }) + libc::CreateFileW(p.as_ptr(), + libc::GENERIC_READ, + libc::FILE_SHARE_READ, + ptr::mut_null(), + libc::OPEN_EXISTING, + libc::FILE_ATTRIBUTE_NORMAL, + ptr::mut_null()) }; if handle as int == libc::INVALID_HANDLE_VALUE as int { return Err(super::last_error()) @@ -453,19 +463,19 @@ pub fn readlink(p: &CString) -> IoResult { pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> { use io::c::compat::kernel32::CreateSymbolicLinkW; - super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| { - as_utf16_p(dst.as_str().unwrap(), |dst| { - unsafe { CreateSymbolicLinkW(dst, src, 0) } - }) as libc::BOOL - })) + let src = try!(to_utf16(src)); + let dst = try!(to_utf16(dst)); + super::mkerr_winbool(unsafe { + CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL + }) } pub fn link(src: &CString, dst: &CString) -> IoResult<()> { - super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| { - as_utf16_p(dst.as_str().unwrap(), |dst| { - unsafe { libc::CreateHardLinkW(dst, src, ptr::mut_null()) } - }) - })) + let src = try!(to_utf16(src)); + let dst = try!(to_utf16(dst)); + super::mkerr_winbool(unsafe { + libc::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::mut_null()) + }) } fn mkstat(stat: &libc::stat) -> rtio::FileStat { @@ -491,12 +501,11 @@ fn mkstat(stat: &libc::stat) -> rtio::FileStat { pub fn stat(p: &CString) -> IoResult { let mut stat: libc::stat = unsafe { mem::zeroed() }; - as_utf16_p(p.as_str().unwrap(), |up| { - match unsafe { libc::wstat(up, &mut stat) } { - 0 => Ok(mkstat(&stat)), - _ => Err(super::last_error()), - } - }) + let p = try!(to_utf16(p)); + match unsafe { libc::wstat(p.as_ptr(), &mut stat) } { + 0 => Ok(mkstat(&stat)), + _ => Err(super::last_error()), + } } pub fn lstat(_p: &CString) -> IoResult { @@ -509,7 +518,8 @@ pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> { actime: (atime / 1000) as libc::time64_t, modtime: (mtime / 1000) as libc::time64_t, }; - super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe { - libc::wutime(p, &buf) - })) + let p = try!(to_utf16(p)); + super::mkerr_libc(unsafe { + libc::wutime(p.as_ptr(), &buf) + }) } diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index 3b0dbe2d0dce9..4c5929ef2233f 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -77,7 +77,7 @@ fn unimpl() -> IoError { IoError { code: ERROR as uint, extra: 0, - detail: None, + detail: Some("not yet supported by the `native` runtime, maybe try `green`.".to_string()), } } diff --git a/src/libnative/io/pipe_win32.rs b/src/libnative/io/pipe_win32.rs index a5694436b9720..45b12aa7007ff 100644 --- a/src/libnative/io/pipe_win32.rs +++ b/src/libnative/io/pipe_win32.rs @@ -88,7 +88,6 @@ use alloc::arc::Arc; use libc; use std::c_str::CString; use std::mem; -use std::os::win32::as_utf16_p; use std::os; use std::ptr; use std::rt::rtio; @@ -98,6 +97,7 @@ use std::rt::mutex; use super::c; use super::util; +use super::file::to_utf16; struct Event(libc::HANDLE); @@ -261,67 +261,66 @@ impl UnixStream { } pub fn connect(addr: &CString, timeout: Option) -> IoResult { - as_utf16_p(addr.as_str().unwrap(), |p| { - let start = ::io::timer::now(); - loop { - match UnixStream::try_connect(p) { - Some(handle) => { - let inner = Inner::new(handle); - let mut mode = libc::PIPE_TYPE_BYTE | - libc::PIPE_READMODE_BYTE | - libc::PIPE_WAIT; - let ret = unsafe { - libc::SetNamedPipeHandleState(inner.handle, - &mut mode, - ptr::mut_null(), - ptr::mut_null()) - }; - return if ret == 0 { - Err(super::last_error()) - } else { - Ok(UnixStream { - inner: Arc::new(inner), - read: None, - write: None, - read_deadline: 0, - write_deadline: 0, - }) - } + let addr = try!(to_utf16(addr)); + let start = ::io::timer::now(); + loop { + match UnixStream::try_connect(addr.as_ptr()) { + Some(handle) => { + let inner = Inner::new(handle); + let mut mode = libc::PIPE_TYPE_BYTE | + libc::PIPE_READMODE_BYTE | + libc::PIPE_WAIT; + let ret = unsafe { + libc::SetNamedPipeHandleState(inner.handle, + &mut mode, + ptr::mut_null(), + ptr::mut_null()) + }; + return if ret == 0 { + Err(super::last_error()) + } else { + Ok(UnixStream { + inner: Arc::new(inner), + read: None, + write: None, + read_deadline: 0, + write_deadline: 0, + }) } - None => {} } + None => {} + } - // On windows, if you fail to connect, you may need to call the - // `WaitNamedPipe` function, and this is indicated with an error - // code of ERROR_PIPE_BUSY. - let code = unsafe { libc::GetLastError() }; - if code as int != libc::ERROR_PIPE_BUSY as int { - return Err(super::last_error()) - } + // On windows, if you fail to connect, you may need to call the + // `WaitNamedPipe` function, and this is indicated with an error + // code of ERROR_PIPE_BUSY. + let code = unsafe { libc::GetLastError() }; + if code as int != libc::ERROR_PIPE_BUSY as int { + return Err(super::last_error()) + } - match timeout { - Some(timeout) => { - let now = ::io::timer::now(); - let timed_out = (now - start) >= timeout || unsafe { - let ms = (timeout - (now - start)) as libc::DWORD; - libc::WaitNamedPipeW(p, ms) == 0 - }; - if timed_out { - return Err(util::timeout("connect timed out")) - } + match timeout { + Some(timeout) => { + let now = ::io::timer::now(); + let timed_out = (now - start) >= timeout || unsafe { + let ms = (timeout - (now - start)) as libc::DWORD; + libc::WaitNamedPipeW(addr.as_ptr(), ms) == 0 + }; + if timed_out { + return Err(util::timeout("connect timed out")) } + } - // An example I found on microsoft's website used 20 - // seconds, libuv uses 30 seconds, hence we make the - // obvious choice of waiting for 25 seconds. - None => { - if unsafe { libc::WaitNamedPipeW(p, 25000) } == 0 { - return Err(super::last_error()) - } + // An example I found on microsoft's website used 20 + // seconds, libuv uses 30 seconds, hence we make the + // obvious choice of waiting for 25 seconds. + None => { + if unsafe { libc::WaitNamedPipeW(addr.as_ptr(), 25000) } == 0 { + return Err(super::last_error()) } } } - }) + } } fn handle(&self) -> libc::HANDLE { self.inner.handle } @@ -564,14 +563,13 @@ impl UnixListener { // Although we technically don't need the pipe until much later, we // create the initial handle up front to test the validity of the name // and such. - as_utf16_p(addr.as_str().unwrap(), |p| { - let ret = unsafe { pipe(p, true) }; - if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE { - Err(super::last_error()) - } else { - Ok(UnixListener { handle: ret, name: addr.clone() }) - } - }) + let addr_v = try!(to_utf16(addr)); + let ret = unsafe { pipe(addr_v.as_ptr(), true) }; + if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE { + Err(super::last_error()) + } else { + Ok(UnixListener { handle: ret, name: addr.clone() }) + } } pub fn native_listen(self) -> IoResult { @@ -639,6 +637,8 @@ impl UnixAcceptor { // using the original server pipe. let handle = self.listener.handle; + let name = try!(to_utf16(&self.listener.name)); + // Once we've got a "server handle", we need to wait for a client to // connect. The ConnectNamedPipe function will block this thread until // someone on the other end connects. This function can "fail" if a @@ -678,9 +678,7 @@ impl UnixAcceptor { // Now that we've got a connected client to our handle, we need to // create a second server pipe. If this fails, we disconnect the // connected client and return an error (see comments above). - let new_handle = as_utf16_p(self.listener.name.as_str().unwrap(), |p| { - unsafe { pipe(p, false) } - }); + let new_handle = unsafe { pipe(name.as_ptr(), false) }; if new_handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE { let ret = Err(super::last_error()); // If our disconnection fails, then there's not really a whole lot diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs index 2c2b7cec1dec4..97b227ae1d8d3 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -296,16 +296,15 @@ fn spawn_process_os(cfg: ProcessConfig, lpSecurityDescriptor: ptr::mut_null(), bInheritHandle: 1, }; - *slot = os::win32::as_utf16_p("NUL", |filename| { - libc::CreateFileW(filename, - access, - libc::FILE_SHARE_READ | - libc::FILE_SHARE_WRITE, - &mut sa, - libc::OPEN_EXISTING, - 0, - ptr::mut_null()) - }); + let filename = "NUL".to_utf16().append_one(0); + *slot = libc::CreateFileW(filename.as_ptr(), + access, + libc::FILE_SHARE_READ | + libc::FILE_SHARE_WRITE, + &mut sa, + libc::OPEN_EXISTING, + 0, + ptr::mut_null()); if *slot == INVALID_HANDLE_VALUE as libc::HANDLE { return Err(super::last_error()) } @@ -338,18 +337,17 @@ fn spawn_process_os(cfg: ProcessConfig, with_envp(cfg.env, |envp| { with_dirp(cfg.cwd, |dirp| { - os::win32::as_mut_utf16_p(cmd_str.as_slice(), |cmdp| { - let created = CreateProcessW(ptr::null(), - cmdp, - ptr::mut_null(), - ptr::mut_null(), - TRUE, - flags, envp, dirp, - &mut si, &mut pi); - if created == FALSE { - create_err = Some(super::last_error()); - } - }) + let mut cmd_str = cmd_str.to_utf16().append_one(0); + let created = CreateProcessW(ptr::null(), + cmd_str.as_mut_ptr(), + ptr::mut_null(), + ptr::mut_null(), + TRUE, + flags, envp, dirp, + &mut si, &mut pi); + if created == FALSE { + create_err = Some(super::last_error()); + } }) }); @@ -740,7 +738,8 @@ fn with_dirp(d: Option<&CString>, cb: |*u16| -> T) -> T { Some(dir) => { let dir_str = dir.as_str() .expect("expected workingdirectory to be utf-8 encoded"); - os::win32::as_utf16_p(dir_str, cb) + let dir_str = dir_str.to_utf16().append_one(0); + cb(dir_str.as_ptr()) }, None => cb(ptr::null()) } diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index 67501c9795d18..0933301970d19 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -17,18 +17,16 @@ A `BigInt` is a combination of `BigUint` and `Sign`. */ use Integer; +use rand::Rng; -use std::cmp; +use std::{cmp, fmt}; use std::default::Default; -use std::fmt; use std::from_str::FromStr; use std::num::CheckedDiv; use std::num::{Bitwise, ToPrimitive, FromPrimitive}; use std::num::{Zero, One, ToStrRadix, FromStrRadix}; -use rand::Rng; use std::string::String; -use std::uint; -use std::{i64, u64}; +use std::{uint, i64, u64}; /** A `BigDigit` is a `BigUint`'s composing element. @@ -94,7 +92,7 @@ impl Eq for BigUint {} impl PartialOrd for BigUint { #[inline] fn lt(&self, other: &BigUint) -> bool { - match self.cmp(other) { Less => true, _ => false} + self.cmp(other) == Less } } @@ -115,7 +113,7 @@ impl Ord for BigUint { impl Default for BigUint { #[inline] - fn default() -> BigUint { BigUint::new(Vec::new()) } + fn default() -> BigUint { Zero::zero() } } impl fmt::Show for BigUint { @@ -605,7 +603,7 @@ impl_to_biguint!(u64, FromPrimitive::from_u64) impl ToStrRadix for BigUint { fn to_str_radix(&self, radix: uint) -> String { - assert!(1 < radix && radix <= 16); + assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]"); let (base, max_len) = get_radix_base(radix); if base == BigDigit::base { return fill_concat(self.data.as_slice(), radix, max_len) @@ -645,8 +643,7 @@ impl ToStrRadix for BigUint { impl FromStrRadix for BigUint { /// Creates and initializes a `BigUint`. #[inline] - fn from_str_radix(s: &str, radix: uint) - -> Option { + fn from_str_radix(s: &str, radix: uint) -> Option { BigUint::parse_bytes(s.as_bytes(), radix) } } @@ -656,14 +653,11 @@ impl BigUint { /// /// The digits are be in base 2^32. #[inline] - pub fn new(v: Vec) -> BigUint { + pub fn new(mut digits: Vec) -> BigUint { // omit trailing zeros - let new_len = v.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1); - - if new_len == v.len() { return BigUint { data: v }; } - let mut v = v; - v.truncate(new_len); - return BigUint { data: v }; + let new_len = digits.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1); + digits.truncate(new_len); + BigUint { data: digits } } /// Creates and initializes a `BigUint`. @@ -671,7 +665,7 @@ impl BigUint { /// The digits are be in base 2^32. #[inline] pub fn from_slice(slice: &[BigDigit]) -> BigUint { - return BigUint::new(Vec::from_slice(slice)); + BigUint::new(Vec::from_slice(slice)) } /// Creates and initializes a `BigUint`. @@ -768,7 +762,6 @@ impl BigUint { // `DoubleBigDigit` size dependent #[inline] fn get_radix_base(radix: uint) -> (DoubleBigDigit, uint) { - assert!(1 < radix && radix <= 16); match radix { 2 => (4294967296, 32), 3 => (3486784401, 20), @@ -785,7 +778,7 @@ fn get_radix_base(radix: uint) -> (DoubleBigDigit, uint) { 14 => (1475789056, 8), 15 => (2562890625, 8), 16 => (4294967296, 8), - _ => fail!() + _ => fail!("The radix must be within (1, 16]") } } @@ -815,7 +808,7 @@ pub struct BigInt { impl PartialEq for BigInt { #[inline] fn eq(&self, other: &BigInt) -> bool { - match self.cmp(other) { Equal => true, _ => false } + self.cmp(other) == Equal } } @@ -824,7 +817,7 @@ impl Eq for BigInt {} impl PartialOrd for BigInt { #[inline] fn lt(&self, other: &BigInt) -> bool { - match self.cmp(other) { Less => true, _ => false} + self.cmp(other) == Less } } @@ -844,7 +837,7 @@ impl Ord for BigInt { impl Default for BigInt { #[inline] - fn default() -> BigInt { BigInt::new(Zero, Vec::new()) } + fn default() -> BigInt { Zero::zero() } } impl fmt::Show for BigInt { @@ -929,8 +922,7 @@ impl Add for BigInt { match (self.sign, other.sign) { (Zero, _) => other.clone(), (_, Zero) => self.clone(), - (Plus, Plus) => BigInt::from_biguint(Plus, - self.data + other.data), + (Plus, Plus) => BigInt::from_biguint(Plus, self.data + other.data), (Plus, Minus) => self - (-*other), (Minus, Plus) => other - (-*self), (Minus, Minus) => -((-self) + (-*other)) @@ -975,7 +967,7 @@ impl Div for BigInt { #[inline] fn div(&self, other: &BigInt) -> BigInt { let (q, _) = self.div_rem(other); - return q; + q } } @@ -983,7 +975,7 @@ impl Rem for BigInt { #[inline] fn rem(&self, other: &BigInt) -> BigInt { let (_, r) = self.div_rem(other); - return r; + r } } @@ -1045,13 +1037,13 @@ impl Integer for BigInt { #[inline] fn div_floor(&self, other: &BigInt) -> BigInt { let (d, _) = self.div_mod_floor(other); - return d; + d } #[inline] fn mod_floor(&self, other: &BigInt) -> BigInt { let (_, m) = self.div_mod_floor(other); - return m; + m } fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) { @@ -1265,7 +1257,7 @@ impl RandBigInt for R { let final_digit: BigDigit = self.gen(); data.push(final_digit >> (BigDigit::bits - rem)); } - return BigUint::new(data); + BigUint::new(data) } fn gen_bigint(&mut self, bit_size: uint) -> BigInt { @@ -1287,7 +1279,7 @@ impl RandBigInt for R { } else { Minus }; - return BigInt::from_biguint(sign, biguint); + BigInt::from_biguint(sign, biguint) } fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint { @@ -1322,8 +1314,8 @@ impl BigInt { /// /// The digits are be in base 2^32. #[inline] - pub fn new(sign: Sign, v: Vec) -> BigInt { - BigInt::from_biguint(sign, BigUint::new(v)) + pub fn new(sign: Sign, digits: Vec) -> BigInt { + BigInt::from_biguint(sign, BigUint::new(digits)) } /// Creates and initializes a `BigInt`. @@ -1334,7 +1326,7 @@ impl BigInt { if sign == Zero || data.is_zero() { return BigInt { sign: Zero, data: Zero::zero() }; } - return BigInt { sign: sign, data: data }; + BigInt { sign: sign, data: data } } /// Creates and initializes a `BigInt`. @@ -1344,8 +1336,7 @@ impl BigInt { } /// Creates and initializes a `BigInt`. - pub fn parse_bytes(buf: &[u8], radix: uint) - -> Option { + pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { if buf.is_empty() { return None; } let mut sign = Plus; let mut start = 0; diff --git a/src/libnum/integer.rs b/src/libnum/integer.rs new file mode 100644 index 0000000000000..d958d40d3d114 --- /dev/null +++ b/src/libnum/integer.rs @@ -0,0 +1,411 @@ +// Copyright 2013-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. + +//! Integer trait and functions + +pub trait Integer: Num + PartialOrd + + Div + + Rem { + /// Simultaneous truncated integer division and modulus + #[inline] + fn div_rem(&self, other: &Self) -> (Self, Self) { + (*self / *other, *self % *other) + } + + /// Floored integer division + /// + /// # Examples + /// + /// ~~~ + /// # use num::Integer; + /// assert!(( 8i).div_floor(& 3) == 2); + /// assert!(( 8i).div_floor(&-3) == -3); + /// assert!((-8i).div_floor(& 3) == -3); + /// assert!((-8i).div_floor(&-3) == 2); + /// + /// assert!(( 1i).div_floor(& 2) == 0); + /// assert!(( 1i).div_floor(&-2) == -1); + /// assert!((-1i).div_floor(& 2) == -1); + /// assert!((-1i).div_floor(&-2) == 0); + /// ~~~ + fn div_floor(&self, other: &Self) -> Self; + + /// Floored integer modulo, satisfying: + /// + /// ~~~ + /// # use num::Integer; + /// # let n = 1i; let d = 1i; + /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n) + /// ~~~ + /// + /// # Examples + /// + /// ~~~ + /// # use num::Integer; + /// assert!(( 8i).mod_floor(& 3) == 2); + /// assert!(( 8i).mod_floor(&-3) == -1); + /// assert!((-8i).mod_floor(& 3) == 1); + /// assert!((-8i).mod_floor(&-3) == -2); + /// + /// assert!(( 1i).mod_floor(& 2) == 1); + /// assert!(( 1i).mod_floor(&-2) == -1); + /// assert!((-1i).mod_floor(& 2) == 1); + /// assert!((-1i).mod_floor(&-2) == -1); + /// ~~~ + fn mod_floor(&self, other: &Self) -> Self; + + /// Simultaneous floored integer division and modulus + fn div_mod_floor(&self, other: &Self) -> (Self, Self) { + (self.div_floor(other), self.mod_floor(other)) + } + + /// Greatest Common Divisor (GCD) + fn gcd(&self, other: &Self) -> Self; + + /// Lowest Common Multiple (LCM) + fn lcm(&self, other: &Self) -> Self; + + /// Returns `true` if `other` divides evenly into `self` + fn divides(&self, other: &Self) -> bool; + + /// Returns `true` if the number is even + fn is_even(&self) -> bool; + + /// Returns `true` if the number is odd + fn is_odd(&self) -> bool; +} + +/// Simultaneous integer division and modulus +#[inline] pub fn div_rem(x: T, y: T) -> (T, T) { x.div_rem(&y) } +/// Floored integer division +#[inline] pub fn div_floor(x: T, y: T) -> T { x.div_floor(&y) } +/// Floored integer modulus +#[inline] pub fn mod_floor(x: T, y: T) -> T { x.mod_floor(&y) } +/// Simultaneous floored integer division and modulus +#[inline] pub fn div_mod_floor(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) } + +/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The +/// result is always positive. +#[inline(always)] pub fn gcd(x: T, y: T) -> T { x.gcd(&y) } +/// Calculates the Lowest Common Multiple (LCM) of the number and `other`. +#[inline(always)] pub fn lcm(x: T, y: T) -> T { x.lcm(&y) } + +macro_rules! impl_integer_for_int { + ($T:ty, $test_mod:ident) => ( + impl Integer for $T { + /// Floored integer division + #[inline] + fn div_floor(&self, other: &$T) -> $T { + // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, + // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) + match self.div_rem(other) { + (d, r) if (r > 0 && *other < 0) + || (r < 0 && *other > 0) => d - 1, + (d, _) => d, + } + } + + /// Floored integer modulo + #[inline] + fn mod_floor(&self, other: &$T) -> $T { + // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, + // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) + match *self % *other { + r if (r > 0 && *other < 0) + || (r < 0 && *other > 0) => r + *other, + r => r, + } + } + + /// Calculates `div_floor` and `mod_floor` simultaneously + #[inline] + fn div_mod_floor(&self, other: &$T) -> ($T,$T) { + // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, + // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) + match self.div_rem(other) { + (d, r) if (r > 0 && *other < 0) + || (r < 0 && *other > 0) => (d - 1, r + *other), + (d, r) => (d, r), + } + } + + /// Calculates the Greatest Common Divisor (GCD) of the number and + /// `other`. The result is always positive. + #[inline] + fn gcd(&self, other: &$T) -> $T { + // Use Euclid's algorithm + let mut m = *self; + let mut n = *other; + while m != 0 { + let temp = m; + m = n % temp; + n = temp; + } + n.abs() + } + + /// Calculates the Lowest Common Multiple (LCM) of the number and + /// `other`. + #[inline] + fn lcm(&self, other: &$T) -> $T { + // should not have to recalculate abs + ((*self * *other) / self.gcd(other)).abs() + } + + /// Returns `true` if the number can be divided by `other` without + /// leaving a remainder + #[inline] + fn divides(&self, other: &$T) -> bool { *self % *other == 0 } + + /// Returns `true` if the number is divisible by `2` + #[inline] + fn is_even(&self) -> bool { self & 1 == 0 } + + /// Returns `true` if the number is not divisible by `2` + #[inline] + fn is_odd(&self) -> bool { !self.is_even() } + } + + #[cfg(test)] + mod $test_mod { + use Integer; + + /// Checks that the division rule holds for: + /// + /// - `n`: numerator (dividend) + /// - `d`: denominator (divisor) + /// - `qr`: quotient and remainder + #[cfg(test)] + fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) { + assert_eq!(d * q + r, n); + } + + #[test] + fn test_div_rem() { + fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) { + let (n,d) = nd; + let separate_div_rem = (n / d, n % d); + let combined_div_rem = n.div_rem(&d); + + assert_eq!(separate_div_rem, qr); + assert_eq!(combined_div_rem, qr); + + test_division_rule(nd, separate_div_rem); + test_division_rule(nd, combined_div_rem); + } + + test_nd_dr(( 8, 3), ( 2, 2)); + test_nd_dr(( 8, -3), (-2, 2)); + test_nd_dr((-8, 3), (-2, -2)); + test_nd_dr((-8, -3), ( 2, -2)); + + test_nd_dr(( 1, 2), ( 0, 1)); + test_nd_dr(( 1, -2), ( 0, 1)); + test_nd_dr((-1, 2), ( 0, -1)); + test_nd_dr((-1, -2), ( 0, -1)); + } + + #[test] + fn test_div_mod_floor() { + fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) { + let (n,d) = nd; + let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d)); + let combined_div_mod_floor = n.div_mod_floor(&d); + + assert_eq!(separate_div_mod_floor, dm); + assert_eq!(combined_div_mod_floor, dm); + + test_division_rule(nd, separate_div_mod_floor); + test_division_rule(nd, combined_div_mod_floor); + } + + test_nd_dm(( 8, 3), ( 2, 2)); + test_nd_dm(( 8, -3), (-3, -1)); + test_nd_dm((-8, 3), (-3, 1)); + test_nd_dm((-8, -3), ( 2, -2)); + + test_nd_dm(( 1, 2), ( 0, 1)); + test_nd_dm(( 1, -2), (-1, -1)); + test_nd_dm((-1, 2), (-1, 1)); + test_nd_dm((-1, -2), ( 0, -1)); + } + + #[test] + fn test_gcd() { + assert_eq!((10 as $T).gcd(&2), 2 as $T); + assert_eq!((10 as $T).gcd(&3), 1 as $T); + assert_eq!((0 as $T).gcd(&3), 3 as $T); + assert_eq!((3 as $T).gcd(&3), 3 as $T); + assert_eq!((56 as $T).gcd(&42), 14 as $T); + assert_eq!((3 as $T).gcd(&-3), 3 as $T); + assert_eq!((-6 as $T).gcd(&3), 3 as $T); + assert_eq!((-4 as $T).gcd(&-2), 2 as $T); + } + + #[test] + fn test_lcm() { + assert_eq!((1 as $T).lcm(&0), 0 as $T); + assert_eq!((0 as $T).lcm(&1), 0 as $T); + assert_eq!((1 as $T).lcm(&1), 1 as $T); + assert_eq!((-1 as $T).lcm(&1), 1 as $T); + assert_eq!((1 as $T).lcm(&-1), 1 as $T); + assert_eq!((-1 as $T).lcm(&-1), 1 as $T); + assert_eq!((8 as $T).lcm(&9), 72 as $T); + assert_eq!((11 as $T).lcm(&5), 55 as $T); + } + + #[test] + fn test_even() { + assert_eq!((-4 as $T).is_even(), true); + assert_eq!((-3 as $T).is_even(), false); + assert_eq!((-2 as $T).is_even(), true); + assert_eq!((-1 as $T).is_even(), false); + assert_eq!((0 as $T).is_even(), true); + assert_eq!((1 as $T).is_even(), false); + assert_eq!((2 as $T).is_even(), true); + assert_eq!((3 as $T).is_even(), false); + assert_eq!((4 as $T).is_even(), true); + } + + #[test] + fn test_odd() { + assert_eq!((-4 as $T).is_odd(), false); + assert_eq!((-3 as $T).is_odd(), true); + assert_eq!((-2 as $T).is_odd(), false); + assert_eq!((-1 as $T).is_odd(), true); + assert_eq!((0 as $T).is_odd(), false); + assert_eq!((1 as $T).is_odd(), true); + assert_eq!((2 as $T).is_odd(), false); + assert_eq!((3 as $T).is_odd(), true); + assert_eq!((4 as $T).is_odd(), false); + } + } + ) +} + +impl_integer_for_int!(i8, test_integer_i8) +impl_integer_for_int!(i16, test_integer_i16) +impl_integer_for_int!(i32, test_integer_i32) +impl_integer_for_int!(i64, test_integer_i64) +impl_integer_for_int!(int, test_integer_int) + +macro_rules! impl_integer_for_uint { + ($T:ty, $test_mod:ident) => ( + impl Integer for $T { + /// Unsigned integer division. Returns the same result as `div` (`/`). + #[inline] + fn div_floor(&self, other: &$T) -> $T { *self / *other } + + /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`). + #[inline] + fn mod_floor(&self, other: &$T) -> $T { *self % *other } + + /// Calculates the Greatest Common Divisor (GCD) of the number and `other` + #[inline] + fn gcd(&self, other: &$T) -> $T { + // Use Euclid's algorithm + let mut m = *self; + let mut n = *other; + while m != 0 { + let temp = m; + m = n % temp; + n = temp; + } + n + } + + /// Calculates the Lowest Common Multiple (LCM) of the number and `other` + #[inline] + fn lcm(&self, other: &$T) -> $T { + (*self * *other) / self.gcd(other) + } + + /// Returns `true` if the number can be divided by `other` without leaving a remainder + #[inline] + fn divides(&self, other: &$T) -> bool { *self % *other == 0 } + + /// Returns `true` if the number is divisible by `2` + #[inline] + fn is_even(&self) -> bool { self & 1 == 0 } + + /// Returns `true` if the number is not divisible by `2` + #[inline] + fn is_odd(&self) -> bool { !self.is_even() } + } + + #[cfg(test)] + mod $test_mod { + use Integer; + + #[test] + fn test_div_mod_floor() { + assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T); + assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T); + assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T)); + assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T); + assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T); + assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T)); + assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T); + assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T); + assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T)); + } + + #[test] + fn test_gcd() { + assert_eq!((10 as $T).gcd(&2), 2 as $T); + assert_eq!((10 as $T).gcd(&3), 1 as $T); + assert_eq!((0 as $T).gcd(&3), 3 as $T); + assert_eq!((3 as $T).gcd(&3), 3 as $T); + assert_eq!((56 as $T).gcd(&42), 14 as $T); + } + + #[test] + fn test_lcm() { + assert_eq!((1 as $T).lcm(&0), 0 as $T); + assert_eq!((0 as $T).lcm(&1), 0 as $T); + assert_eq!((1 as $T).lcm(&1), 1 as $T); + assert_eq!((8 as $T).lcm(&9), 72 as $T); + assert_eq!((11 as $T).lcm(&5), 55 as $T); + assert_eq!((99 as $T).lcm(&17), 1683 as $T); + } + + #[test] + fn test_divides() { + assert!((6 as $T).divides(&(6 as $T))); + assert!((6 as $T).divides(&(3 as $T))); + assert!((6 as $T).divides(&(1 as $T))); + } + + #[test] + fn test_even() { + assert_eq!((0 as $T).is_even(), true); + assert_eq!((1 as $T).is_even(), false); + assert_eq!((2 as $T).is_even(), true); + assert_eq!((3 as $T).is_even(), false); + assert_eq!((4 as $T).is_even(), true); + } + + #[test] + fn test_odd() { + assert_eq!((0 as $T).is_odd(), false); + assert_eq!((1 as $T).is_odd(), true); + assert_eq!((2 as $T).is_odd(), false); + assert_eq!((3 as $T).is_odd(), true); + assert_eq!((4 as $T).is_odd(), false); + } + } + ) +} + +impl_integer_for_uint!(u8, test_integer_u8) +impl_integer_for_uint!(u16, test_integer_u16) +impl_integer_for_uint!(u32, test_integer_u32) +impl_integer_for_uint!(u64, test_integer_u64) +impl_integer_for_uint!(uint, test_integer_uint) diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs index fae21e80f3072..709882c87cedb 100644 --- a/src/libnum/lib.rs +++ b/src/libnum/lib.rs @@ -57,406 +57,12 @@ extern crate rand; +pub use bigint::{BigInt, BigUint}; +pub use rational::{Rational, BigRational}; +pub use complex::Complex; +pub use integer::Integer; + pub mod bigint; -pub mod rational; pub mod complex; - -pub trait Integer: Num + PartialOrd - + Div - + Rem { - /// Simultaneous truncated integer division and modulus - #[inline] - fn div_rem(&self, other: &Self) -> (Self, Self) { - (*self / *other, *self % *other) - } - - /// Floored integer division - /// - /// # Examples - /// - /// ~~~ - /// # use num::Integer; - /// assert!(( 8i).div_floor(& 3) == 2); - /// assert!(( 8i).div_floor(&-3) == -3); - /// assert!((-8i).div_floor(& 3) == -3); - /// assert!((-8i).div_floor(&-3) == 2); - /// - /// assert!(( 1i).div_floor(& 2) == 0); - /// assert!(( 1i).div_floor(&-2) == -1); - /// assert!((-1i).div_floor(& 2) == -1); - /// assert!((-1i).div_floor(&-2) == 0); - /// ~~~ - fn div_floor(&self, other: &Self) -> Self; - - /// Floored integer modulo, satisfying: - /// - /// ~~~ - /// # use num::Integer; - /// # let n = 1i; let d = 1i; - /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n) - /// ~~~ - /// - /// # Examples - /// - /// ~~~ - /// # use num::Integer; - /// assert!(( 8i).mod_floor(& 3) == 2); - /// assert!(( 8i).mod_floor(&-3) == -1); - /// assert!((-8i).mod_floor(& 3) == 1); - /// assert!((-8i).mod_floor(&-3) == -2); - /// - /// assert!(( 1i).mod_floor(& 2) == 1); - /// assert!(( 1i).mod_floor(&-2) == -1); - /// assert!((-1i).mod_floor(& 2) == 1); - /// assert!((-1i).mod_floor(&-2) == -1); - /// ~~~ - fn mod_floor(&self, other: &Self) -> Self; - - /// Simultaneous floored integer division and modulus - fn div_mod_floor(&self, other: &Self) -> (Self, Self) { - (self.div_floor(other), self.mod_floor(other)) - } - - /// Greatest Common Divisor (GCD) - fn gcd(&self, other: &Self) -> Self; - - /// Lowest Common Multiple (LCM) - fn lcm(&self, other: &Self) -> Self; - - /// Returns `true` if `other` divides evenly into `self` - fn divides(&self, other: &Self) -> bool; - - /// Returns `true` if the number is even - fn is_even(&self) -> bool; - - /// Returns `true` if the number is odd - fn is_odd(&self) -> bool; -} - -/// Simultaneous integer division and modulus -#[inline] pub fn div_rem(x: T, y: T) -> (T, T) { x.div_rem(&y) } -/// Floored integer division -#[inline] pub fn div_floor(x: T, y: T) -> T { x.div_floor(&y) } -/// Floored integer modulus -#[inline] pub fn mod_floor(x: T, y: T) -> T { x.mod_floor(&y) } -/// Simultaneous floored integer division and modulus -#[inline] pub fn div_mod_floor(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) } - -/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The -/// result is always positive. -#[inline(always)] pub fn gcd(x: T, y: T) -> T { x.gcd(&y) } -/// Calculates the Lowest Common Multiple (LCM) of the number and `other`. -#[inline(always)] pub fn lcm(x: T, y: T) -> T { x.lcm(&y) } - -macro_rules! impl_integer_for_int { - ($T:ty, $test_mod:ident) => ( - impl Integer for $T { - /// Floored integer division - #[inline] - fn div_floor(&self, other: &$T) -> $T { - // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, - // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - match self.div_rem(other) { - (d, r) if (r > 0 && *other < 0) - || (r < 0 && *other > 0) => d - 1, - (d, _) => d, - } - } - - /// Floored integer modulo - #[inline] - fn mod_floor(&self, other: &$T) -> $T { - // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, - // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - match *self % *other { - r if (r > 0 && *other < 0) - || (r < 0 && *other > 0) => r + *other, - r => r, - } - } - - /// Calculates `div_floor` and `mod_floor` simultaneously - #[inline] - fn div_mod_floor(&self, other: &$T) -> ($T,$T) { - // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, - // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - match self.div_rem(other) { - (d, r) if (r > 0 && *other < 0) - || (r < 0 && *other > 0) => (d - 1, r + *other), - (d, r) => (d, r), - } - } - - /// Calculates the Greatest Common Divisor (GCD) of the number and - /// `other`. The result is always positive. - #[inline] - fn gcd(&self, other: &$T) -> $T { - // Use Euclid's algorithm - let mut m = *self; - let mut n = *other; - while m != 0 { - let temp = m; - m = n % temp; - n = temp; - } - n.abs() - } - - /// Calculates the Lowest Common Multiple (LCM) of the number and - /// `other`. - #[inline] - fn lcm(&self, other: &$T) -> $T { - // should not have to recalculate abs - ((*self * *other) / self.gcd(other)).abs() - } - - /// Returns `true` if the number can be divided by `other` without - /// leaving a remainder - #[inline] - fn divides(&self, other: &$T) -> bool { *self % *other == 0 } - - /// Returns `true` if the number is divisible by `2` - #[inline] - fn is_even(&self) -> bool { self & 1 == 0 } - - /// Returns `true` if the number is not divisible by `2` - #[inline] - fn is_odd(&self) -> bool { !self.is_even() } - } - - #[cfg(test)] - mod $test_mod { - use Integer; - - /// Checks that the division rule holds for: - /// - /// - `n`: numerator (dividend) - /// - `d`: denominator (divisor) - /// - `qr`: quotient and remainder - #[cfg(test)] - fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) { - assert_eq!(d * q + r, n); - } - - #[test] - fn test_div_rem() { - fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) { - let (n,d) = nd; - let separate_div_rem = (n / d, n % d); - let combined_div_rem = n.div_rem(&d); - - assert_eq!(separate_div_rem, qr); - assert_eq!(combined_div_rem, qr); - - test_division_rule(nd, separate_div_rem); - test_division_rule(nd, combined_div_rem); - } - - test_nd_dr(( 8, 3), ( 2, 2)); - test_nd_dr(( 8, -3), (-2, 2)); - test_nd_dr((-8, 3), (-2, -2)); - test_nd_dr((-8, -3), ( 2, -2)); - - test_nd_dr(( 1, 2), ( 0, 1)); - test_nd_dr(( 1, -2), ( 0, 1)); - test_nd_dr((-1, 2), ( 0, -1)); - test_nd_dr((-1, -2), ( 0, -1)); - } - - #[test] - fn test_div_mod_floor() { - fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) { - let (n,d) = nd; - let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d)); - let combined_div_mod_floor = n.div_mod_floor(&d); - - assert_eq!(separate_div_mod_floor, dm); - assert_eq!(combined_div_mod_floor, dm); - - test_division_rule(nd, separate_div_mod_floor); - test_division_rule(nd, combined_div_mod_floor); - } - - test_nd_dm(( 8, 3), ( 2, 2)); - test_nd_dm(( 8, -3), (-3, -1)); - test_nd_dm((-8, 3), (-3, 1)); - test_nd_dm((-8, -3), ( 2, -2)); - - test_nd_dm(( 1, 2), ( 0, 1)); - test_nd_dm(( 1, -2), (-1, -1)); - test_nd_dm((-1, 2), (-1, 1)); - test_nd_dm((-1, -2), ( 0, -1)); - } - - #[test] - fn test_gcd() { - assert_eq!((10 as $T).gcd(&2), 2 as $T); - assert_eq!((10 as $T).gcd(&3), 1 as $T); - assert_eq!((0 as $T).gcd(&3), 3 as $T); - assert_eq!((3 as $T).gcd(&3), 3 as $T); - assert_eq!((56 as $T).gcd(&42), 14 as $T); - assert_eq!((3 as $T).gcd(&-3), 3 as $T); - assert_eq!((-6 as $T).gcd(&3), 3 as $T); - assert_eq!((-4 as $T).gcd(&-2), 2 as $T); - } - - #[test] - fn test_lcm() { - assert_eq!((1 as $T).lcm(&0), 0 as $T); - assert_eq!((0 as $T).lcm(&1), 0 as $T); - assert_eq!((1 as $T).lcm(&1), 1 as $T); - assert_eq!((-1 as $T).lcm(&1), 1 as $T); - assert_eq!((1 as $T).lcm(&-1), 1 as $T); - assert_eq!((-1 as $T).lcm(&-1), 1 as $T); - assert_eq!((8 as $T).lcm(&9), 72 as $T); - assert_eq!((11 as $T).lcm(&5), 55 as $T); - } - - #[test] - fn test_even() { - assert_eq!((-4 as $T).is_even(), true); - assert_eq!((-3 as $T).is_even(), false); - assert_eq!((-2 as $T).is_even(), true); - assert_eq!((-1 as $T).is_even(), false); - assert_eq!((0 as $T).is_even(), true); - assert_eq!((1 as $T).is_even(), false); - assert_eq!((2 as $T).is_even(), true); - assert_eq!((3 as $T).is_even(), false); - assert_eq!((4 as $T).is_even(), true); - } - - #[test] - fn test_odd() { - assert_eq!((-4 as $T).is_odd(), false); - assert_eq!((-3 as $T).is_odd(), true); - assert_eq!((-2 as $T).is_odd(), false); - assert_eq!((-1 as $T).is_odd(), true); - assert_eq!((0 as $T).is_odd(), false); - assert_eq!((1 as $T).is_odd(), true); - assert_eq!((2 as $T).is_odd(), false); - assert_eq!((3 as $T).is_odd(), true); - assert_eq!((4 as $T).is_odd(), false); - } - } - ) -} - -impl_integer_for_int!(i8, test_integer_i8) -impl_integer_for_int!(i16, test_integer_i16) -impl_integer_for_int!(i32, test_integer_i32) -impl_integer_for_int!(i64, test_integer_i64) -impl_integer_for_int!(int, test_integer_int) - -macro_rules! impl_integer_for_uint { - ($T:ty, $test_mod:ident) => ( - impl Integer for $T { - /// Unsigned integer division. Returns the same result as `div` (`/`). - #[inline] - fn div_floor(&self, other: &$T) -> $T { *self / *other } - - /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`). - #[inline] - fn mod_floor(&self, other: &$T) -> $T { *self % *other } - - /// Calculates the Greatest Common Divisor (GCD) of the number and `other` - #[inline] - fn gcd(&self, other: &$T) -> $T { - // Use Euclid's algorithm - let mut m = *self; - let mut n = *other; - while m != 0 { - let temp = m; - m = n % temp; - n = temp; - } - n - } - - /// Calculates the Lowest Common Multiple (LCM) of the number and `other` - #[inline] - fn lcm(&self, other: &$T) -> $T { - (*self * *other) / self.gcd(other) - } - - /// Returns `true` if the number can be divided by `other` without leaving a remainder - #[inline] - fn divides(&self, other: &$T) -> bool { *self % *other == 0 } - - /// Returns `true` if the number is divisible by `2` - #[inline] - fn is_even(&self) -> bool { self & 1 == 0 } - - /// Returns `true` if the number is not divisible by `2` - #[inline] - fn is_odd(&self) -> bool { !self.is_even() } - } - - #[cfg(test)] - mod $test_mod { - use Integer; - - #[test] - fn test_div_mod_floor() { - assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T); - assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T); - assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T)); - assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T); - assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T); - assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T)); - assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T); - assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T); - assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T)); - } - - #[test] - fn test_gcd() { - assert_eq!((10 as $T).gcd(&2), 2 as $T); - assert_eq!((10 as $T).gcd(&3), 1 as $T); - assert_eq!((0 as $T).gcd(&3), 3 as $T); - assert_eq!((3 as $T).gcd(&3), 3 as $T); - assert_eq!((56 as $T).gcd(&42), 14 as $T); - } - - #[test] - fn test_lcm() { - assert_eq!((1 as $T).lcm(&0), 0 as $T); - assert_eq!((0 as $T).lcm(&1), 0 as $T); - assert_eq!((1 as $T).lcm(&1), 1 as $T); - assert_eq!((8 as $T).lcm(&9), 72 as $T); - assert_eq!((11 as $T).lcm(&5), 55 as $T); - assert_eq!((99 as $T).lcm(&17), 1683 as $T); - } - - #[test] - fn test_divides() { - assert!((6 as $T).divides(&(6 as $T))); - assert!((6 as $T).divides(&(3 as $T))); - assert!((6 as $T).divides(&(1 as $T))); - } - - #[test] - fn test_even() { - assert_eq!((0 as $T).is_even(), true); - assert_eq!((1 as $T).is_even(), false); - assert_eq!((2 as $T).is_even(), true); - assert_eq!((3 as $T).is_even(), false); - assert_eq!((4 as $T).is_even(), true); - } - - #[test] - fn test_odd() { - assert_eq!((0 as $T).is_odd(), false); - assert_eq!((1 as $T).is_odd(), true); - assert_eq!((2 as $T).is_odd(), false); - assert_eq!((3 as $T).is_odd(), true); - assert_eq!((4 as $T).is_odd(), false); - } - } - ) -} - -impl_integer_for_uint!(u8, test_integer_u8) -impl_integer_for_uint!(u16, test_integer_u16) -impl_integer_for_uint!(u32, test_integer_u32) -impl_integer_for_uint!(u64, test_integer_u64) -impl_integer_for_uint!(uint, test_integer_uint) +pub mod integer; +pub mod rational; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index c7ad74dce571c..0a88abd67d9df 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -321,3 +321,8 @@ pub fn get_reachable_extern_fns(cstore: &cstore::CStore, cnum: ast::CrateNum) let cdata = cstore.get_crate_data(cnum); decoder::get_reachable_extern_fns(&*cdata) } + +pub fn is_typedef(cstore: &cstore::CStore, did: ast::DefId) -> bool { + let cdata = cstore.get_crate_data(did.krate); + decoder::is_typedef(&*cdata, did.node) +} diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 8a2c3c08d419a..56d6766e1b719 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1339,3 +1339,11 @@ pub fn get_reachable_extern_fns(cdata: Cmd) -> Vec { }); return ret; } + +pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool { + let item_doc = lookup_item(id, cdata.data()); + match item_family(item_doc) { + Type => true, + _ => false, + } +} diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 9033b83d47420..ec46e7f8592d3 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -13,7 +13,7 @@ use std::cell::RefCell; use std::os; use std::io::fs; -use std::unstable::dynamic_lib::DynamicLibrary; +use std::dynamic_lib::DynamicLibrary; use std::collections::HashSet; use myfs = util::fs; diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index ba50a15a82ba7..97ffcf279ae73 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -16,7 +16,7 @@ use plugin::registry::Registry; use std::mem; use std::os; -use std::unstable::dynamic_lib::DynamicLibrary; +use std::dynamic_lib::DynamicLibrary; use syntax::ast; use syntax::attr; use syntax::visit; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 2a4774ffd84d4..d243c61ddaff8 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -203,7 +203,7 @@ fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct { fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum { let t = ty::lookup_item_type(tcx, did); match ty::get(t.ty).sty { - ty::ty_enum(edid, _) => { + ty::ty_enum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => { return clean::EnumItem(clean::Enum { generics: t.generics.clean(), variants_stripped: false, diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index fea6748660bde..8ad10a686e677 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -135,7 +135,6 @@ mod imp { mod imp { use libc; use std::mem; - use std::os::win32::as_utf16_p; use std::os; use std::ptr; @@ -162,8 +161,9 @@ mod imp { impl Lock { pub fn new(p: &Path) -> Lock { - let handle = as_utf16_p(p.as_str().unwrap(), |p| unsafe { - libc::CreateFileW(p, + let p_16 = p.as_str().unwrap().to_utf16().append_one(0); + let handle = unsafe { + libc::CreateFileW(p_16.as_ptr(), libc::FILE_GENERIC_READ | libc::FILE_GENERIC_WRITE, libc::FILE_SHARE_READ | @@ -173,7 +173,7 @@ mod imp { libc::CREATE_ALWAYS, libc::FILE_ATTRIBUTE_NORMAL, ptr::mut_null()) - }); + }; if handle as uint == libc::INVALID_HANDLE_VALUE as uint { fail!("create file error: {}", os::last_os_error()); } diff --git a/src/librustdoc/plugins.rs b/src/librustdoc/plugins.rs index 7a796e97f412f..fee1d63a274d5 100644 --- a/src/librustdoc/plugins.rs +++ b/src/librustdoc/plugins.rs @@ -10,7 +10,7 @@ use clean; -use dl = std::unstable::dynamic_lib; +use dl = std::dynamic_lib; use serialize::json; use std::string::String; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3436305829791..0d77764127465 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -15,7 +15,7 @@ use std::io::{Command, TempDir}; use std::os; use std::str; use std::string::String; -use std::unstable::dynamic_lib::DynamicLibrary; +use std::dynamic_lib::DynamicLibrary; use std::collections::{HashSet, HashMap}; use testing; diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/dynamic_lib.rs similarity index 98% rename from src/libstd/unstable/dynamic_lib.rs rename to src/libstd/dynamic_lib.rs index c05cdc85cc53a..fa6efc8a4b18a 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -16,6 +16,9 @@ A simple wrapper over the platform's dynamic library facilities */ +#![experimental] +#![allow(missing_doc)] + use clone::Clone; use c_str::ToCStr; use iter::Iterator; @@ -272,21 +275,21 @@ pub mod dl { #[cfg(target_os = "win32")] pub mod dl { + use c_str::ToCStr; use libc; use os; use ptr; use result::{Ok, Err, Result}; - use string::String; + use str::StrAllocating; use str; - use c_str::ToCStr; + use string::String; pub unsafe fn open_external(filename: T) -> *u8 { // Windows expects Unicode data let filename_cstr = filename.to_c_str(); let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap(); - os::win32::as_utf16_p(filename_str, |raw_name| { - LoadLibraryW(raw_name as *libc::c_void) as *u8 - }) + let filename_str = filename_str.to_utf16().append_one(0); + LoadLibraryW(filename_str.as_ptr() as *libc::c_void) as *u8 } pub unsafe fn open_internal() -> *u8 { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 6f3eec01e8e34..a1e0fa889789f 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -81,13 +81,18 @@ Some examples of obvious things you might want to do * Make a simple TCP client connection and request - ```rust,should_fail + ```rust # #![allow(unused_must_use)] use std::io::net::tcp::TcpStream; + # // connection doesn't fail if a server is running on 8080 + # // locally, we still want to be type checking this code, so lets + # // just stop it running (#11576) + # if false { let mut socket = TcpStream::connect("127.0.0.1", 8080).unwrap(); socket.write(bytes!("GET / HTTP/1.0\n\n")); let response = socket.read_to_end(); + # } ``` * Make a simple TCP server diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 85813c02d5535..e147997334ccc 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -241,15 +241,12 @@ pub mod sync; /* Runtime and platform support */ pub mod c_vec; +pub mod dynamic_lib; pub mod os; pub mod io; pub mod path; pub mod fmt; -// Private APIs -#[unstable] -pub mod unstable; - // FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable' // but name resolution doesn't work without it being pub. #[unstable] @@ -279,3 +276,11 @@ mod std { // The test runner requires std::slice::Vector, so re-export std::slice just for it. #[cfg(test)] pub use slice; } + +#[deprecated] +#[allow(missing_doc)] +#[doc(hiden)] +pub mod unstable { + #[deprecated = "use std::dynamic_lib"] + pub use dynamic_lib; +} diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 90df18106f0a5..fa882e7d016fe 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -133,7 +133,7 @@ pub mod win32 { use os::TMPBUF_SZ; use slice::{MutableVector, ImmutableVector}; use string::String; - use str::{StrSlice, StrAllocating}; + use str::StrSlice; use str; use vec::Vec; @@ -171,17 +171,6 @@ pub mod win32 { return res; } } - - pub fn as_utf16_p(s: &str, f: |*u16| -> T) -> T { - as_mut_utf16_p(s, |t| { f(t as *u16) }) - } - - pub fn as_mut_utf16_p(s: &str, f: |*mut u16| -> T) -> T { - let mut t = s.to_utf16(); - // Null terminate before passing on. - t.push(0u16); - f(t.as_mut_ptr()) - } } /* @@ -356,11 +345,10 @@ pub fn getenv_as_bytes(n: &str) -> Option> { pub fn getenv(n: &str) -> Option { unsafe { with_env_lock(|| { - use os::win32::{as_utf16_p, fill_utf16_buf_and_decode}; - as_utf16_p(n, |u| { - fill_utf16_buf_and_decode(|buf, sz| { - libc::GetEnvironmentVariableW(u, buf, sz) - }) + use os::win32::{fill_utf16_buf_and_decode}; + let n = n.to_utf16().append_one(0); + fill_utf16_buf_and_decode(|buf, sz| { + libc::GetEnvironmentVariableW(n.as_ptr(), buf, sz) }) }) } @@ -398,14 +386,11 @@ pub fn setenv(n: &str, v: &str) { /// Sets the environment variable `n` to the value `v` for the currently running /// process pub fn setenv(n: &str, v: &str) { + let n = n.to_utf16().append_one(0); + let v = v.to_utf16().append_one(0); unsafe { with_env_lock(|| { - use os::win32::as_utf16_p; - as_utf16_p(n, |nbuf| { - as_utf16_p(v, |vbuf| { - libc::SetEnvironmentVariableW(nbuf, vbuf); - }) - }) + libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr()); }) } } @@ -428,12 +413,10 @@ pub fn unsetenv(n: &str) { } #[cfg(windows)] fn _unsetenv(n: &str) { + let n = n.to_utf16().append_one(0); unsafe { with_env_lock(|| { - use os::win32::as_utf16_p; - as_utf16_p(n, |nbuf| { - libc::SetEnvironmentVariableW(nbuf, ptr::null()); - }) + libc::SetEnvironmentVariableW(n.as_ptr(), ptr::null()); }) } } @@ -732,11 +715,12 @@ pub fn change_dir(p: &Path) -> bool { #[cfg(windows)] fn chdir(p: &Path) -> bool { + let p = match p.as_str() { + Some(s) => s.to_utf16().append_one(0), + None => return false, + }; unsafe { - use os::win32::as_utf16_p; - return as_utf16_p(p.as_str().unwrap(), |buf| { - libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL) - }); + libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) } } diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 83fc95267afdf..423f372f018fd 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -614,7 +614,7 @@ mod imp { use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; use slice::ImmutableVector; use str::StrSlice; - use unstable::dynamic_lib::DynamicLibrary; + use dynamic_lib::DynamicLibrary; #[allow(non_snake_case_functions)] extern "system" { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 9e562a08ff95e..7d94e46a88a6e 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -271,6 +271,12 @@ pub fn test_main_static_x(args: &[~str], tests: &[TestDescAndFn]) { tests) } +pub enum ColorConfig { + AutoColor, + AlwaysColor, + NeverColor, +} + pub struct TestOpts { pub filter: Option, pub run_ignored: bool, @@ -282,6 +288,7 @@ pub struct TestOpts { pub test_shard: Option<(uint,uint)>, pub logfile: Option, pub nocapture: bool, + pub color: ColorConfig, } impl TestOpts { @@ -298,6 +305,7 @@ impl TestOpts { test_shard: None, logfile: None, nocapture: false, + color: AutoColor, } } } @@ -324,7 +332,11 @@ fn optgroups() -> Vec { getopts::optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite", "A.B"), getopts::optflag("", "nocapture", "don't capture stdout/stderr of each \ - task, allow printing directly")) + task, allow printing directly"), + getopts::optopt("", "color", "Configure coloring of output: + auto = colorize if stdout is a tty and tests are run on serially (default); + always = always colorize output; + never = never colorize output;", "auto|always|never")) } fn usage(binary: &str) { @@ -406,6 +418,16 @@ pub fn parse_opts(args: &[String]) -> Option { nocapture = os::getenv("RUST_TEST_NOCAPTURE").is_some(); } + let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) { + Some("auto") | None => AutoColor, + Some("always") => AlwaysColor, + Some("never") => NeverColor, + + Some(v) => return Some(Err(format!("argument for --color must be \ + auto, always, or never (was {})", + v))), + }; + let test_opts = TestOpts { filter: filter, run_ignored: run_ignored, @@ -417,6 +439,7 @@ pub fn parse_opts(args: &[String]) -> Option { test_shard: test_shard, logfile: logfile, nocapture: nocapture, + color: color, }; Some(Ok(test_opts)) @@ -492,7 +515,7 @@ impl ConsoleTestState { Ok(ConsoleTestState { out: out, log_out: log_out, - use_color: use_color(), + use_color: use_color(opts), total: 0u, passed: 0u, failed: 0u, @@ -867,8 +890,12 @@ fn should_sort_failures_before_printing_them() { assert!(apos < bpos); } -fn use_color() -> bool { - get_concurrency() == 1 && io::stdout().get_ref().isatty() +fn use_color(opts: &TestOpts) -> bool { + match opts.color { + AutoColor => get_concurrency() == 1 && io::stdout().get_ref().isatty(), + AlwaysColor => true, + NeverColor => false, + } } #[deriving(Clone)] diff --git a/src/test/auxiliary/linkage-visibility.rs b/src/test/auxiliary/linkage-visibility.rs index 4ae0b6f14f59d..0b4bea49fa249 100644 --- a/src/test/auxiliary/linkage-visibility.rs +++ b/src/test/auxiliary/linkage-visibility.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::unstable::dynamic_lib::DynamicLibrary; +use std::dynamic_lib::DynamicLibrary; #[no_mangle] pub fn foo() { bar(); } diff --git a/src/libstd/unstable/mod.rs b/src/test/compile-fail/issue-13446.rs similarity index 71% rename from src/libstd/unstable/mod.rs rename to src/test/compile-fail/issue-13446.rs index 985ef2e142cfd..0bb6ded00121d 100644 --- a/src/libstd/unstable/mod.rs +++ b/src/test/compile-fail/issue-13446.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![doc(hidden)] -pub mod dynamic_lib; +// Used to cause ICE + +static VEC: [u32, ..256] = vec!(); //~ ERROR mismatched types + +fn main() {} + diff --git a/src/test/run-make/extern-fn-reachable/main.rs b/src/test/run-make/extern-fn-reachable/main.rs index e05d43145d7e2..0f759efb02539 100644 --- a/src/test/run-make/extern-fn-reachable/main.rs +++ b/src/test/run-make/extern-fn-reachable/main.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::unstable::dynamic_lib::DynamicLibrary; +use std::dynamic_lib::DynamicLibrary; use std::os; pub fn main() { diff --git a/src/test/run-pass/linkage-visibility.rs b/src/test/run-pass/linkage-visibility.rs index e263767990a65..58f66314e4430 100644 --- a/src/test/run-pass/linkage-visibility.rs +++ b/src/test/run-pass/linkage-visibility.rs @@ -10,7 +10,7 @@ // aux-build:linkage-visibility.rs // ignore-android: FIXME(#10379) -// ignore-win32: std::unstable::dynamic_lib does not work on win32 well +// ignore-win32: std::dynamic_lib does not work on win32 well extern crate foo = "linkage-visibility";