From 64fe93e49dc0c6a552c5f08507064f2ce12800ca Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 20 Feb 2015 12:00:26 -0800 Subject: std: Tidy up some `unsafe impl`s for `sync` This commit removes many unnecessary `unsafe impl` blocks as well as pushing the needed implementations to the lowest level possible. I noticed that the bounds for `RwLock` are a little off when reviewing #22574 and wanted to ensure that we had our story straight on these implementations. --- src/libstd/sys/unix/condvar.rs | 6 +++++- src/libstd/sys/unix/mutex.rs | 4 +++- src/libstd/sys/unix/rwlock.rs | 5 +++++ src/libstd/sys/windows/condvar.rs | 5 +++++ src/libstd/sys/windows/mutex.rs | 17 ++++++++++------- src/libstd/sys/windows/rwlock.rs | 5 +++++ 6 files changed, 33 insertions(+), 9 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index 3bc41473152..90dfebc4c45 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; use libc; use ptr; -use std::option::Option::{Some, None}; use sys::mutex::{self, Mutex}; use sys::time; use sys::sync as ffi; @@ -20,6 +21,9 @@ use num::{Int, NumCast}; pub struct Condvar { inner: UnsafeCell } +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + pub const CONDVAR_INIT: Condvar = Condvar { inner: UnsafeCell { value: ffi::PTHREAD_COND_INITIALIZER }, }; diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs index 9e1527aef20..f87c0339533 100644 --- a/src/libstd/sys/unix/mutex.rs +++ b/src/libstd/sys/unix/mutex.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; -use marker::Sync; use sys::sync as ffi; use sys_common::mutex; @@ -24,6 +25,7 @@ pub const MUTEX_INIT: Mutex = Mutex { inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER }, }; +unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} impl Mutex { diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs index 54523e0076d..b857f4ab75f 100644 --- a/src/libstd/sys/unix/rwlock.rs +++ b/src/libstd/sys/unix/rwlock.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; use sys::sync as ffi; @@ -17,6 +19,9 @@ pub const RWLOCK_INIT: RWLock = RWLock { inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER }, }; +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} + impl RWLock { #[inline] pub unsafe fn new() -> RWLock { diff --git a/src/libstd/sys/windows/condvar.rs b/src/libstd/sys/windows/condvar.rs index db8038006fd..071637e3a93 100644 --- a/src/libstd/sys/windows/condvar.rs +++ b/src/libstd/sys/windows/condvar.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; use libc::{self, DWORD}; use os; @@ -17,6 +19,9 @@ use time::Duration; pub struct Condvar { inner: UnsafeCell } +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + pub const CONDVAR_INIT: Condvar = Condvar { inner: UnsafeCell { value: ffi::CONDITION_VARIABLE_INIT } }; diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 75495efc7cb..0847f3b52bf 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use marker::Sync; +use prelude::v1::*; + use cell::UnsafeCell; use sys::sync as ffi; @@ -18,6 +19,7 @@ pub const MUTEX_INIT: Mutex = Mutex { inner: UnsafeCell { value: ffi::SRWLOCK_INIT } }; +unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} #[inline] @@ -27,14 +29,15 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK { // So you might be asking why we're using SRWLock instead of CriticalSection? // -// 1. SRWLock is several times faster than CriticalSection according to benchmarks performed on both -// Windows 8 and Windows 7. +// 1. SRWLock is several times faster than CriticalSection according to +// benchmarks performed on both Windows 8 and Windows 7. // -// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix implementation -// deadlocks so consistency is preferred. See #19962 for more details. +// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix +// implementation deadlocks so consistency is preferred. See #19962 for more +// details. // -// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy is there there are -// no guarantees of fairness. +// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy +// is there there are no guarantees of fairness. impl Mutex { #[inline] diff --git a/src/libstd/sys/windows/rwlock.rs b/src/libstd/sys/windows/rwlock.rs index 76fe352ed77..009605535a0 100644 --- a/src/libstd/sys/windows/rwlock.rs +++ b/src/libstd/sys/windows/rwlock.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; use sys::sync as ffi; @@ -17,6 +19,9 @@ pub const RWLOCK_INIT: RWLock = RWLock { inner: UnsafeCell { value: ffi::SRWLOCK_INIT } }; +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} + impl RWLock { #[inline] pub unsafe fn read(&self) { -- cgit 1.4.1-3-g733a5 From d0c589d5ced5006f72d766af2ccecf699ff76176 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 23 Feb 2015 23:50:32 +0100 Subject: Hide unnecessary error checking from the user This affects the `set_non_blocking` function which cannot fail for Unix or Windows, given correct parameters. Additionally, the short UDP write error case has been removed as there is no such thing as "short UDP writes", instead, the operating system will error out if the application tries to send a packet larger than the MTU of the network path. --- src/libstd/sys/common/net.rs | 21 ++++++++------------- src/libstd/sys/unix/mod.rs | 4 ++-- src/libstd/sys/unix/pipe.rs | 6 +++--- src/libstd/sys/unix/process.rs | 6 +++--- src/libstd/sys/unix/tcp.rs | 6 +++--- src/libstd/sys/windows/mod.rs | 6 +++--- src/libstd/sys/windows/net.rs | 13 ++++++++++++- src/libstd/sys/windows/tcp.rs | 2 +- 8 files changed, 35 insertions(+), 29 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index b5cd42219e1..228362e3d62 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -503,7 +503,7 @@ pub fn connect_timeout(fd: sock_t, #[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK; // Make sure the call to connect() doesn't block - try!(set_nonblocking(fd, true)); + set_nonblocking(fd, true); let ret = match unsafe { libc::connect(fd, addrp, len) } { // If the connection is in progress, then we need to wait for it to @@ -533,7 +533,7 @@ pub fn connect_timeout(fd: sock_t, }; // be sure to turn blocking I/O back on - try!(set_nonblocking(fd, false)); + set_nonblocking(fd, false); return ret; #[cfg(unix)] @@ -626,7 +626,7 @@ pub struct Guard<'a> { #[unsafe_destructor] impl<'a> Drop for Guard<'a> { fn drop(&mut self) { - assert!(set_nonblocking(self.fd, false).is_ok()); + set_nonblocking(self.fd, false); } } @@ -723,7 +723,7 @@ impl TcpStream { fd: self.fd(), guard: self.inner.lock.lock().unwrap(), }; - assert!(set_nonblocking(self.fd(), true).is_ok()); + set_nonblocking(self.fd(), true); ret } @@ -862,7 +862,7 @@ impl UdpSocket { fd: self.fd(), guard: self.inner.lock.lock().unwrap(), }; - assert!(set_nonblocking(self.fd(), true).is_ok()); + set_nonblocking(self.fd(), true); ret } @@ -887,9 +887,7 @@ impl UdpSocket { storagep, &mut addrlen) as libc::c_int })); - sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| { - Ok((n as uint, addr)) - }) + Ok((n as uint, sockaddr_to_addr(&storage, addrlen as uint).unwrap())) } pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> { @@ -910,11 +908,8 @@ impl UdpSocket { }; let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite)); - if n != buf.len() { - Err(short_write(n, "couldn't send entire packet at once")) - } else { - Ok(()) - } + assert!(n == buf.len(), "UDP packet not completely written."); + Ok(()) } pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> { diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index b79ad7031fa..632270bc5cc 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -214,9 +214,9 @@ pub fn wouldblock() -> bool { err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32 } -pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> { +pub fn set_nonblocking(fd: sock_t, nb: bool) { let set = nb as libc::c_int; - mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })) + mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })).unwrap(); } // nothing needed on unix platforms diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 3c9cdc65975..1446600a77e 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -235,9 +235,9 @@ impl UnixListener { _ => { let (reader, writer) = try!(unsafe { sys::os::pipe() }); - try!(set_nonblocking(reader.fd(), true)); - try!(set_nonblocking(writer.fd(), true)); - try!(set_nonblocking(self.fd(), true)); + set_nonblocking(reader.fd(), true); + set_nonblocking(writer.fd(), true); + set_nonblocking(self.fd(), true); Ok(UnixAcceptor { inner: Arc::new(AcceptorInner { listener: self, diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 2be841989e6..dc067e7e0c5 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -345,8 +345,8 @@ impl Process { unsafe { let mut pipes = [0; 2]; assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0); - set_nonblocking(pipes[0], true).ok().unwrap(); - set_nonblocking(pipes[1], true).ok().unwrap(); + set_nonblocking(pipes[0], true); + set_nonblocking(pipes[1], true); WRITE_FD = pipes[1]; let mut old: c::sigaction = mem::zeroed(); @@ -362,7 +362,7 @@ impl Process { fn waitpid_helper(input: libc::c_int, messages: Receiver, (read_fd, old): (libc::c_int, c::sigaction)) { - set_nonblocking(input, true).ok().unwrap(); + set_nonblocking(input, true); let mut set: c::fd_set = unsafe { mem::zeroed() }; let mut tv: libc::timeval; let mut active = Vec::<(libc::pid_t, Sender, u64)>::new(); diff --git a/src/libstd/sys/unix/tcp.rs b/src/libstd/sys/unix/tcp.rs index c8f9d318482..b08f6ef9b90 100644 --- a/src/libstd/sys/unix/tcp.rs +++ b/src/libstd/sys/unix/tcp.rs @@ -67,9 +67,9 @@ impl TcpListener { -1 => Err(last_net_error()), _ => { let (reader, writer) = try!(unsafe { sys::os::pipe() }); - try!(set_nonblocking(reader.fd(), true)); - try!(set_nonblocking(writer.fd(), true)); - try!(set_nonblocking(self.fd(), true)); + set_nonblocking(reader.fd(), true); + set_nonblocking(writer.fd(), true); + set_nonblocking(self.fd(), true); Ok(TcpAcceptor { inner: Arc::new(AcceptorInner { listener: self, diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index a756fb29f81..a13c03c7448 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -192,13 +192,13 @@ pub fn wouldblock() -> bool { err == libc::WSAEWOULDBLOCK as i32 } -pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> { +pub fn set_nonblocking(fd: sock_t, nb: bool) { let mut set = nb as libc::c_ulong; - if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } { + (if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) } != 0 { Err(last_error()) } else { Ok(()) - } + }).unwrap(); } pub fn init_net() { diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 3451232f40a..6caa4df5dfe 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -25,6 +25,8 @@ pub type wrlen_t = i32; pub struct Socket(libc::SOCKET); +/// Checks whether the Windows socket interface has been started already, and +/// if not, starts it. pub fn init() { static START: Once = ONCE_INIT; @@ -38,10 +40,16 @@ pub fn init() { }); } +/// Returns the last error from the Windows socket interface. fn last_error() -> io::Error { io::Error::from_os_error(unsafe { c::WSAGetLastError() }) } +/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1) +/// and if so, returns the last error from the Windows socket interface. . This +/// function must be called before another call to the socket API is made. +/// +/// FIXME: generics needed? pub fn cvt(t: T) -> io::Result { let one: T = Int::one(); if t == -one { @@ -51,11 +59,14 @@ pub fn cvt(t: T) -> io::Result { } } +/// Provides the functionality of `cvt` for the return values of `getaddrinfo` +/// and similar, meaning that they return an error if the return value is 0. pub fn cvt_gai(err: c_int) -> io::Result<()> { if err == 0 { return Ok(()) } cvt(err).map(|_| ()) } +/// Provides the functionality of `cvt` for a closure. pub fn cvt_r(mut f: F) -> io::Result where F: FnMut() -> T { cvt(f()) } @@ -112,7 +123,7 @@ impl Socket { impl Drop for Socket { fn drop(&mut self) { - unsafe { let _ = libc::closesocket(self.0); } + unsafe { cvt(libc::closesocket(self.0)).unwrap(); } } } diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs index 4804ca510cb..25b70918591 100644 --- a/src/libstd/sys/windows/tcp.rs +++ b/src/libstd/sys/windows/tcp.rs @@ -192,7 +192,7 @@ impl TcpAcceptor { c::WSAEventSelect(socket, events[1], 0) }; if ret != 0 { return Err(last_net_error()) } - try!(set_nonblocking(socket, false)); + set_nonblocking(socket, false); return Ok(stream) } } -- cgit 1.4.1-3-g733a5 From 537d6946e4570a9425aa5c881454e67bedf210b0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Feb 2015 15:26:18 -0800 Subject: std: Expose a `mode` accessor for Permissions on unix Currently we have a `set_mode` mutator, so this just adds the pairing of a `mode` accessor to read the value. Closes #22738 --- src/libstd/fs.rs | 4 ++++ src/libstd/sys/unix/ext.rs | 3 +++ src/libstd/sys/unix/fs2.rs | 1 + 3 files changed, 8 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 98c1b50a9bf..c6ceced4598 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -325,6 +325,10 @@ impl FromInner for Permissions { } } +impl AsInner for Permissions { + fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 } +} + impl Iterator for ReadDir { type Item = io::Result; diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index b8b9dcfb3c6..3f9da6e3c51 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -173,10 +173,13 @@ impl OsStrExt for OsStr { // Unix-specific extensions to `Permissions` pub trait PermissionsExt { + fn mode(&self) -> i32; fn set_mode(&mut self, mode: i32); } impl PermissionsExt for Permissions { + fn mode(&self) -> i32 { self.as_inner().mode() } + fn set_mode(&mut self, mode: i32) { *self = FromInner::from_inner(FromInner::from_inner(mode)); } diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index 92a47c6c385..d77e76241cc 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -86,6 +86,7 @@ impl FilePermissions { self.mode |= 0o222; } } + pub fn mode(&self) -> i32 { self.mode as i32 } } impl FromInner for FilePermissions { -- cgit 1.4.1-3-g733a5 From 0afebe63dd0b8e01cac824e86de7df6d6fd29bbd Mon Sep 17 00:00:00 2001 From: Eunji Jeong Date: Tue, 24 Feb 2015 18:15:03 +0900 Subject: Replace deprecated getdtablesize() with sysconf(_SC_OPEN_MAX) for android aarch64 --- src/libstd/sys/unix/process.rs | 10 +++++++++- src/libstd/sys/unix/process2.rs | 11 ++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 2be841989e6..02e6d7dadb1 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -69,7 +69,6 @@ impl Process { K: BytesContainer + Eq + Hash, V: BytesContainer { use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp}; - use libc::funcs::bsd44::getdtablesize; mod rustrt { extern { @@ -82,6 +81,15 @@ impl Process { assert_eq!(ret, 0); } + #[cfg(all(target_os = "android", target_arch = "aarch64"))] + unsafe fn getdtablesize() -> c_int { + libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int + } + #[cfg(not(all(target_os = "android", target_arch = "aarch64")))] + unsafe fn getdtablesize() -> c_int { + libc::funcs::bsd44::getdtablesize() + } + let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null()); // temporary until unboxed closures land diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs index 06fa5c4bba7..b7a1b002f55 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process2.rs @@ -141,7 +141,6 @@ impl Process { -> io::Result { use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp}; - use libc::funcs::bsd44::getdtablesize; mod rustrt { extern { @@ -154,6 +153,16 @@ impl Process { assert_eq!(ret, 0); } + #[cfg(all(target_os = "android", target_arch = "aarch64"))] + unsafe fn getdtablesize() -> c_int { + libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int + } + + #[cfg(not(all(target_os = "android", target_arch = "aarch64")))] + unsafe fn getdtablesize() -> c_int { + libc::funcs::bsd44::getdtablesize() + } + let dirp = cfg.cwd.as_ref().map(|c| c.as_ptr()).unwrap_or(ptr::null()); with_envp(cfg.env.as_ref(), |envp: *const c_void| { -- cgit 1.4.1-3-g733a5 From 54b11066bb9af585f161164000c43fdfe21c646f Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 24 Feb 2015 17:01:50 +0100 Subject: Revert a wrong replace of "fail" to "panic" --- src/libstd/sys/windows/tty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index 8a8b5309057..c9bac69c434 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -52,7 +52,7 @@ fn invalid_encoding() -> IoError { pub fn is_tty(fd: c_int) -> bool { let mut out: DWORD = 0; - // If this function doesn't panic then fd is a TTY + // If this function doesn't return an error, then fd is a TTY match unsafe { GetConsoleMode(get_osfhandle(fd) as HANDLE, &mut out as LPDWORD) } { 0 => false, -- cgit 1.4.1-3-g733a5 From 0fc1a7da93e5d431f5cd54a3f1263e2a5f9e5748 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 24 Feb 2015 17:07:13 +0100 Subject: Improve readability of an error check in `set_non_blocking` --- src/libstd/sys/windows/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index a13c03c7448..3acb372f658 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -194,11 +194,11 @@ pub fn wouldblock() -> bool { pub fn set_nonblocking(fd: sock_t, nb: bool) { let mut set = nb as libc::c_ulong; - (if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) } != 0 { - Err(last_error()) - } else { - Ok(()) - }).unwrap(); + if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) } != 0 { + // The above function should not return an error unless we passed it + // invalid parameters. Panic on errors. + Err(last_error()).unwrap(); + } } pub fn init_net() { -- cgit 1.4.1-3-g733a5 From 2807a1ce0255ce98415ebe6f65eb589d0f2f894b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 24 Feb 2015 21:15:45 +0300 Subject: Use arrays instead of vectors in tests --- src/doc/trpl/macros.md | 2 +- src/libcollections/binary_heap.rs | 2 +- src/libcollections/bit.rs | 12 ++-- src/libcollections/btree/map.rs | 4 +- src/libcollections/btree/set.rs | 20 +++---- src/libcollections/enum_set.rs | 22 +++---- src/libcollections/linked_list.rs | 4 +- src/libcollections/macros.rs | 2 +- src/libcollections/slice.rs | 40 ++++++------- src/libcollections/str.rs | 70 +++++++++++------------ src/libcollections/string.rs | 6 +- src/libcollections/vec.rs | 62 ++++++++++---------- src/libcollections/vec_deque.rs | 14 ++--- src/libcollections/vec_map.rs | 6 +- src/libcore/iter.rs | 4 +- src/libcore/option.rs | 2 +- src/libcore/result.rs | 4 +- src/libcoretest/iter.rs | 53 +++++++---------- src/libcoretest/mem.rs | 2 +- src/libcoretest/nonzero.rs | 2 +- src/libcoretest/ptr.rs | 2 +- src/libcoretest/str.rs | 32 +++++------ src/librbml/io.rs | 2 +- src/librustc_driver/test.rs | 10 ++-- src/libserialize/json.rs | 10 ++-- src/libstd/old_io/extensions.rs | 16 +++--- src/libstd/old_io/mem.rs | 18 +++--- src/libstd/old_io/result.rs | 2 +- src/libstd/old_io/util.rs | 20 +++---- src/libstd/sys/common/wtf8.rs | 6 +- src/libsyntax/ext/expand.rs | 6 +- src/libsyntax/ext/mtwt.rs | 24 ++++---- src/libsyntax/util/small_vector.rs | 4 +- src/libterm/terminfo/parm.rs | 6 +- src/test/run-pass/auto-ref-sliceable.rs | 2 +- src/test/run-pass/coerce-reborrow-mut-vec-arg.rs | 2 +- src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs | 2 +- src/test/run-pass/generic-static-methods.rs | 2 +- src/test/run-pass/monad.rs | 12 ++-- src/test/run-pass/trait-generic.rs | 8 +-- src/test/run-pass/unboxed-closures-infer-upvar.rs | 2 +- 41 files changed, 254 insertions(+), 267 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md index ce6fa3ce949..49da298bb3f 100644 --- a/src/doc/trpl/macros.md +++ b/src/doc/trpl/macros.md @@ -73,7 +73,7 @@ macro_rules! vec { }; } # fn main() { -# assert_eq!(&[1,2,3], &vec![1,2,3]); +# assert_eq!([1,2,3], vec![1,2,3]); # } ``` diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 9f549fd7237..36c76dbad14 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -480,7 +480,7 @@ impl BinaryHeap { /// heap.push(3); /// /// let vec = heap.into_sorted_vec(); - /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7]); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]); /// ``` pub fn into_sorted_vec(mut self) -> Vec { let mut end = self.len(); diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index f28f9976f0c..61bb204a443 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -640,13 +640,13 @@ impl BitVec { /// let mut bv = BitVec::from_elem(3, true); /// bv.set(1, false); /// - /// assert_eq!(bv.to_bytes(), vec!(0b10100000)); + /// assert_eq!(bv.to_bytes(), [0b10100000]); /// /// let mut bv = BitVec::from_elem(9, false); /// bv.set(2, true); /// bv.set(8, true); /// - /// assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); + /// assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]); /// ``` pub fn to_bytes(&self) -> Vec { fn bit(bit_vec: &BitVec, byte: usize, bit: usize) -> u8 { @@ -806,7 +806,7 @@ impl BitVec { /// let mut bv = BitVec::from_bytes(&[0b01001011]); /// bv.grow(2, true); /// assert_eq!(bv.len(), 10); - /// assert_eq!(bv.to_bytes(), vec!(0b01001011, 0b11000000)); + /// assert_eq!(bv.to_bytes(), [0b01001011, 0b11000000]); /// ``` pub fn grow(&mut self, n: usize, value: bool) { // Note: we just bulk set all the bits in the last word in this fn in multiple places @@ -2285,12 +2285,12 @@ mod tests { fn test_to_bytes() { let mut bv = BitVec::from_elem(3, true); bv.set(1, false); - assert_eq!(bv.to_bytes(), vec!(0b10100000)); + assert_eq!(bv.to_bytes(), [0b10100000]); let mut bv = BitVec::from_elem(9, false); bv.set(2, true); bv.set(8, true); - assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); + assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]); } #[test] @@ -2675,7 +2675,7 @@ mod bit_set_test { let bit_vec: BitSet = usizes.into_iter().collect(); let idxs: Vec<_> = bit_vec.iter().collect(); - assert_eq!(idxs, vec![0, 2, 3]); + assert_eq!(idxs, [0, 2, 3]); let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect(); let real: Vec<_> = range_step(0, 10000, 2).collect(); diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 1b456eec830..6b83253faed 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -1281,7 +1281,7 @@ impl BTreeMap { /// a.insert(2, "b"); /// /// let keys: Vec = a.keys().cloned().collect(); - /// assert_eq!(keys, vec![1,2,]); + /// assert_eq!(keys, [1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { @@ -1303,7 +1303,7 @@ impl BTreeMap { /// a.insert(2, "b"); /// /// let values: Vec<&str> = a.values().cloned().collect(); - /// assert_eq!(values, vec!["a","b"]); + /// assert_eq!(values, ["a", "b"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn values<'a>(&'a self) -> Values<'a, K, V> { diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 929b2f58043..8a668a23dbb 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -121,7 +121,7 @@ impl BTreeSet { /// } /// /// let v: Vec = set.iter().cloned().collect(); - /// assert_eq!(v, vec![1,2,3,4]); + /// assert_eq!(v, [1, 2, 3, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { @@ -138,7 +138,7 @@ impl BTreeSet { /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); /// /// let v: Vec = set.into_iter().collect(); - /// assert_eq!(v, vec![1,2,3,4]); + /// assert_eq!(v, [1, 2, 3, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_iter(self) -> IntoIter { @@ -197,7 +197,7 @@ impl BTreeSet { /// b.insert(3); /// /// let diff: Vec = a.difference(&b).cloned().collect(); - /// assert_eq!(diff, vec![1]); + /// assert_eq!(diff, [1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> { @@ -220,7 +220,7 @@ impl BTreeSet { /// b.insert(3); /// /// let sym_diff: Vec = a.symmetric_difference(&b).cloned().collect(); - /// assert_eq!(sym_diff, vec![1,3]); + /// assert_eq!(sym_diff, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet) @@ -244,7 +244,7 @@ impl BTreeSet { /// b.insert(3); /// /// let intersection: Vec = a.intersection(&b).cloned().collect(); - /// assert_eq!(intersection, vec![2]); + /// assert_eq!(intersection, [2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn intersection<'a>(&'a self, other: &'a BTreeSet) @@ -266,7 +266,7 @@ impl BTreeSet { /// b.insert(2); /// /// let union: Vec = a.union(&b).cloned().collect(); - /// assert_eq!(union, vec![1,2]); + /// assert_eq!(union, [1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T> { @@ -534,7 +534,7 @@ impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet> for &'a BTreeSet { /// /// let result = &a - &b; /// let result_vec: Vec<_> = result.into_iter().collect(); - /// assert_eq!(result_vec, vec![1, 2]); + /// assert_eq!(result_vec, [1, 2]); /// ``` fn sub(self, rhs: &BTreeSet) -> BTreeSet { self.difference(rhs).cloned().collect() @@ -557,7 +557,7 @@ impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet> for &'a BTreeSet { /// /// let result = &a ^ &b; /// let result_vec: Vec<_> = result.into_iter().collect(); - /// assert_eq!(result_vec, vec![1, 4]); + /// assert_eq!(result_vec, [1, 4]); /// ``` fn bitxor(self, rhs: &BTreeSet) -> BTreeSet { self.symmetric_difference(rhs).cloned().collect() @@ -580,7 +580,7 @@ impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet> for &'a BTreeSet { /// /// let result = &a & &b; /// let result_vec: Vec<_> = result.into_iter().collect(); - /// assert_eq!(result_vec, vec![2, 3]); + /// assert_eq!(result_vec, [2, 3]); /// ``` fn bitand(self, rhs: &BTreeSet) -> BTreeSet { self.intersection(rhs).cloned().collect() @@ -603,7 +603,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet> for &'a BTreeSet { /// /// let result = &a | &b; /// let result_vec: Vec<_> = result.into_iter().collect(); - /// assert_eq!(result_vec, vec![1, 2, 3, 4, 5]); + /// assert_eq!(result_vec, [1, 2, 3, 4, 5]); /// ``` fn bitor(self, rhs: &BTreeSet) -> BTreeSet { self.union(rhs).cloned().collect() diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 0c957426060..12c5d7a9cc6 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -428,19 +428,19 @@ mod test { e1.insert(A); let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!(vec![A], elems); + assert_eq!([A], elems); e1.insert(C); let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!(vec![A,C], elems); + assert_eq!([A,C], elems); e1.insert(C); let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!(vec![A,C], elems); + assert_eq!([A,C], elems); e1.insert(B); let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!(vec![A,B,C], elems); + assert_eq!([A,B,C], elems); } /////////////////////////////////////////////////////////////////////////// @@ -458,35 +458,35 @@ mod test { let e_union = e1 | e2; let elems: ::vec::Vec<_> = e_union.iter().collect(); - assert_eq!(vec![A,B,C], elems); + assert_eq!([A,B,C], elems); let e_intersection = e1 & e2; let elems: ::vec::Vec<_> = e_intersection.iter().collect(); - assert_eq!(vec![C], elems); + assert_eq!([C], elems); // Another way to express intersection let e_intersection = e1 - (e1 - e2); let elems: ::vec::Vec<_> = e_intersection.iter().collect(); - assert_eq!(vec![C], elems); + assert_eq!([C], elems); let e_subtract = e1 - e2; let elems: ::vec::Vec<_> = e_subtract.iter().collect(); - assert_eq!(vec![A], elems); + assert_eq!([A], elems); // Bitwise XOR of two sets, aka symmetric difference let e_symmetric_diff = e1 ^ e2; let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(vec![A,B], elems); + assert_eq!([A,B], elems); // Another way to express symmetric difference let e_symmetric_diff = (e1 - e2) | (e2 - e1); let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(vec![A,B], elems); + assert_eq!([A,B], elems); // Yet another way to express symmetric difference let e_symmetric_diff = (e1 | e2) - (e1 & e2); let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(vec![A,B], elems); + assert_eq!([A,B], elems); } #[test] diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 3c61fc3da90..aa9bd5b0fed 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -777,7 +777,7 @@ impl<'a, A> IterMut<'a, A> { /// } /// { /// let vec: Vec<_> = list.into_iter().collect(); - /// assert_eq!(vec, vec![1, 2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); /// } /// ``` #[inline] @@ -1273,7 +1273,7 @@ mod tests { } check_links(&m); assert_eq!(m.len(), 3 + len * 2); - assert_eq!(m.into_iter().collect::>(), vec![-2,0,1,2,3,4,5,6,7,8,9,0,1]); + assert_eq!(m.into_iter().collect::>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]); } #[test] diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index ebcfb8d1cf8..e9764547628 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -26,7 +26,7 @@ /// /// ``` /// let v = vec![1; 3]; -/// assert_eq!(v, vec![1, 1, 1]); +/// assert_eq!(v, [1, 1, 1]); /// ``` /// /// Note that unlike array expressions this syntax supports all elements diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 776b8b3af14..6850e8c0f8e 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1779,10 +1779,10 @@ mod tests { let mut v = vec![1, 2, 3, 4, 5]; let mut e = v.swap_remove(0); assert_eq!(e, 1); - assert_eq!(v, vec![5, 2, 3, 4]); + assert_eq!(v, [5, 2, 3, 4]); e = v.swap_remove(3); assert_eq!(e, 4); - assert_eq!(v, vec![5, 2, 3]); + assert_eq!(v, [5, 2, 3]); } #[test] @@ -1890,7 +1890,7 @@ mod tests { fn test_retain() { let mut v = vec![1, 2, 3, 4, 5]; v.retain(is_odd); - assert_eq!(v, vec![1, 3, 5]); + assert_eq!(v, [1, 3, 5]); } #[test] @@ -2159,45 +2159,45 @@ mod tests { let v: [Vec; 0] = []; let c = v.concat(); assert_eq!(c, []); - let d = [vec![1], vec![2,3]].concat(); - assert_eq!(d, vec![1, 2, 3]); + let d = [vec![1], vec![2, 3]].concat(); + assert_eq!(d, [1, 2, 3]); let v: &[&[_]] = &[&[1], &[2, 3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 3]); + assert_eq!(v.connect(&0), [1, 0, 2, 3]); let v: &[&[_]] = &[&[1], &[2], &[3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]); + assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); } #[test] fn test_connect() { let v: [Vec; 0] = []; - assert_eq!(v.connect(&0), vec![]); - assert_eq!([vec![1], vec![2, 3]].connect(&0), vec![1, 0, 2, 3]); - assert_eq!([vec![1], vec![2], vec![3]].connect(&0), vec![1, 0, 2, 0, 3]); + assert_eq!(v.connect(&0), []); + assert_eq!([vec![1i], vec![2, 3]].connect(&0), [1, 0, 2, 3]); + assert_eq!([vec![1i], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]); let v: [&[_]; 2] = [&[1], &[2, 3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 3]); + assert_eq!(v.connect(&0), [1, 0, 2, 3]); let v: [&[_]; 3] = [&[1], &[2], &[3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]); + assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); } #[test] fn test_insert() { let mut a = vec![1, 2, 4]; a.insert(2, 3); - assert_eq!(a, vec![1, 2, 3, 4]); + assert_eq!(a, [1, 2, 3, 4]); let mut a = vec![1, 2, 3]; a.insert(0, 0); - assert_eq!(a, vec![0, 1, 2, 3]); + assert_eq!(a, [0, 1, 2, 3]); let mut a = vec![1, 2, 3]; a.insert(3, 4); - assert_eq!(a, vec![1, 2, 3, 4]); + assert_eq!(a, [1, 2, 3, 4]); let mut a = vec![]; a.insert(0, 1); - assert_eq!(a, vec![1]); + assert_eq!(a, [1]); } #[test] @@ -2212,16 +2212,16 @@ mod tests { let mut a = vec![1, 2, 3, 4]; assert_eq!(a.remove(2), 3); - assert_eq!(a, vec![1, 2, 4]); + assert_eq!(a, [1, 2, 4]); assert_eq!(a.remove(2), 4); - assert_eq!(a, vec![1, 2]); + assert_eq!(a, [1, 2]); assert_eq!(a.remove(0), 1); - assert_eq!(a, vec![2]); + assert_eq!(a, [2]); assert_eq!(a.remove(0), 2); - assert_eq!(a, vec![]); + assert_eq!(a, []); } #[test] diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index f3b2e973897..c58cca828d8 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -552,7 +552,7 @@ pub trait StrExt: Index { /// ``` /// let v: Vec = "abc åäö".chars().collect(); /// - /// assert_eq!(v, vec!['a', 'b', 'c', ' ', 'å', 'ä', 'ö']); + /// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn chars(&self) -> Chars { @@ -600,20 +600,20 @@ pub trait StrExt: Index { /// /// ``` /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); - /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); /// /// let v: Vec<&str> = "".split('X').collect(); - /// assert_eq!(v, vec![""]); + /// assert_eq!(v, [""]); /// ``` /// /// More complex patterns with a lambda: /// /// ``` /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); - /// assert_eq!(v, vec!["abc", "def", "ghi"]); + /// assert_eq!(v, ["abc", "def", "ghi"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); - /// assert_eq!(v, vec!["lion", "", "tiger", "leopard"]); + /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { @@ -632,23 +632,23 @@ pub trait StrExt: Index { /// /// ``` /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect(); - /// assert_eq!(v, vec!["Mary", "had", "a little lambda"]); + /// assert_eq!(v, ["Mary", "had", "a little lambda"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect(); - /// assert_eq!(v, vec!["lion", "", "tigerXleopard"]); + /// assert_eq!(v, ["lion", "", "tigerXleopard"]); /// /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect(); - /// assert_eq!(v, vec!["abcXdef"]); + /// assert_eq!(v, ["abcXdef"]); /// /// let v: Vec<&str> = "".splitn(1, 'X').collect(); - /// assert_eq!(v, vec![""]); + /// assert_eq!(v, [""]); /// ``` /// /// More complex patterns with a lambda: /// /// ``` /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect(); - /// assert_eq!(v, vec!["abc", "def2ghi"]); + /// assert_eq!(v, ["abc", "def2ghi"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { @@ -669,17 +669,17 @@ pub trait StrExt: Index { /// /// ``` /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); - /// assert_eq!(v, vec!["A", "B"]); + /// assert_eq!(v, ["A", "B"]); /// /// let v: Vec<&str> = "A..B..".split_terminator('.').collect(); - /// assert_eq!(v, vec!["A", "", "B", ""]); + /// assert_eq!(v, ["A", "", "B", ""]); /// ``` /// /// More complex patterns with a lambda: /// /// ``` /// let v: Vec<&str> = "abc1def2ghi3".split_terminator(|c: char| c.is_numeric()).collect(); - /// assert_eq!(v, vec!["abc", "def", "ghi"]); + /// assert_eq!(v, ["abc", "def", "ghi"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { @@ -699,17 +699,17 @@ pub trait StrExt: Index { /// /// ``` /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect(); - /// assert_eq!(v, vec!["lamb", "little", "Mary had a"]); + /// assert_eq!(v, ["lamb", "little", "Mary had a"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect(); - /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]); + /// assert_eq!(v, ["leopard", "tiger", "lionX"]); /// ``` /// /// More complex patterns with a lambda: /// /// ``` /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect(); - /// assert_eq!(v, vec!["ghi", "abc1def"]); + /// assert_eq!(v, ["ghi", "abc1def"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> { @@ -727,13 +727,13 @@ pub trait StrExt: Index { /// /// ``` /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect(); - /// assert_eq!(v, vec![(0,3), (6,9), (12,15)]); + /// assert_eq!(v, [(0,3), (6,9), (12,15)]); /// /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect(); - /// assert_eq!(v, vec![(1,4), (4,7)]); + /// assert_eq!(v, [(1,4), (4,7)]); /// /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect(); - /// assert_eq!(v, vec![(0, 3)]); // only the first `aba` + /// assert_eq!(v, [(0, 3)]); // only the first `aba` /// ``` #[unstable(feature = "collections", reason = "might have its iterator type changed")] @@ -749,10 +749,10 @@ pub trait StrExt: Index { /// /// ``` /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect(); - /// assert_eq!(v, vec!["", "XXX", "YYY", ""]); + /// assert_eq!(v, ["", "XXX", "YYY", ""]); /// /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect(); - /// assert_eq!(v, vec!["1", "", "2"]); + /// assert_eq!(v, ["1", "", "2"]); /// ``` #[unstable(feature = "collections")] #[deprecated(since = "1.0.0", reason = "use `split()` with a `&str`")] @@ -770,7 +770,7 @@ pub trait StrExt: Index { /// let four_lines = "foo\nbar\n\nbaz"; /// let v: Vec<&str> = four_lines.lines().collect(); /// - /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); + /// assert_eq!(v, ["foo", "bar", "", "baz"]); /// ``` /// /// Leaving off the trailing character: @@ -779,7 +779,7 @@ pub trait StrExt: Index { /// let four_lines = "foo\nbar\n\nbaz\n"; /// let v: Vec<&str> = four_lines.lines().collect(); /// - /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); + /// assert_eq!(v, ["foo", "bar", "", "baz"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn lines(&self) -> Lines { @@ -796,7 +796,7 @@ pub trait StrExt: Index { /// let four_lines = "foo\r\nbar\n\r\nbaz"; /// let v: Vec<&str> = four_lines.lines_any().collect(); /// - /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); + /// assert_eq!(v, ["foo", "bar", "", "baz"]); /// ``` /// /// Leaving off the trailing character: @@ -805,7 +805,7 @@ pub trait StrExt: Index { /// let four_lines = "foo\r\nbar\n\r\nbaz\n"; /// let v: Vec<&str> = four_lines.lines_any().collect(); /// - /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); + /// assert_eq!(v, ["foo", "bar", "", "baz"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn lines_any(&self) -> LinesAny { @@ -1441,7 +1441,7 @@ pub trait StrExt: Index { /// let some_words = " Mary had\ta little \n\t lamb"; /// let v: Vec<&str> = some_words.words().collect(); /// - /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); /// ``` #[unstable(feature = "str_words", reason = "the precise algorithm to use is unclear")] @@ -2400,17 +2400,17 @@ mod tests { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; let split: Vec<&str> = data.splitn(3, ' ').collect(); - assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect(); - assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); // Unicode let split: Vec<&str> = data.splitn(3, 'ä').collect(); - assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); + assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect(); - assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); + assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); } #[test] @@ -2418,17 +2418,17 @@ mod tests { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; let split: Vec<&str> = data.split('\n').collect(); - assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); let split: Vec<&str> = data.split_terminator('\n').collect(); - assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); } #[test] fn test_words() { let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; let words: Vec<&str> = data.words().collect(); - assert_eq!(words, vec!["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) + assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) } #[test] @@ -2513,11 +2513,11 @@ mod tests { fn test_lines() { let data = "\nMäry häd ä little lämb\n\nLittle lämb\n"; let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]); + assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]); + assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); } #[test] diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 6c2624cd204..e9070cff207 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -120,7 +120,7 @@ impl String { /// let invalid_vec = vec![240, 144, 128]; /// let s = String::from_utf8(invalid_vec).err().unwrap(); /// assert_eq!(s.utf8_error(), Utf8Error::TooShort); - /// assert_eq!(s.into_bytes(), vec![240, 144, 128]); + /// assert_eq!(s.into_bytes(), [240, 144, 128]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -340,7 +340,7 @@ impl String { /// ``` /// let s = String::from_str("hello"); /// let bytes = s.into_bytes(); - /// assert_eq!(bytes, vec![104, 101, 108, 108, 111]); + /// assert_eq!(bytes, [104, 101, 108, 108, 111]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -619,7 +619,7 @@ impl String { /// let mut s = String::from_str("hello"); /// unsafe { /// let vec = s.as_mut_vec(); - /// assert!(vec == &mut vec![104, 101, 108, 108, 111]); + /// assert!(vec == &[104, 101, 108, 108, 111]); /// vec.reverse(); /// } /// assert_eq!(s.as_slice(), "olleh"); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 3f5f9288916..c446618649d 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -93,7 +93,7 @@ use borrow::{Cow, IntoCow}; /// for x in vec.iter() { /// println!("{}", x); /// } -/// assert_eq!(vec, vec![7, 1, 2, 3]); +/// assert_eq!(vec, [7, 1, 2, 3]); /// ``` /// /// The `vec!` macro is provided to make initialization more convenient: @@ -101,7 +101,7 @@ use borrow::{Cow, IntoCow}; /// ``` /// let mut vec = vec![1, 2, 3]; /// vec.push(4); -/// assert_eq!(vec, vec![1, 2, 3, 4]); +/// assert_eq!(vec, [1, 2, 3, 4]); /// ``` /// /// Use a `Vec` as an efficient stack: @@ -242,7 +242,7 @@ impl Vec { /// /// // Put everything back together into a Vec /// let rebuilt = Vec::from_raw_parts(p, len, cap); - /// assert_eq!(rebuilt, vec![4, 5, 6]); + /// assert_eq!(rebuilt, [4, 5, 6]); /// } /// } /// ``` @@ -404,7 +404,7 @@ impl Vec { /// ``` /// let mut vec = vec![1, 2, 3, 4]; /// vec.truncate(2); - /// assert_eq!(vec, vec![1, 2]); + /// assert_eq!(vec, [1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { @@ -505,10 +505,10 @@ impl Vec { /// let mut v = vec!["foo", "bar", "baz", "qux"]; /// /// assert_eq!(v.swap_remove(1), "bar"); - /// assert_eq!(v, vec!["foo", "qux", "baz"]); + /// assert_eq!(v, ["foo", "qux", "baz"]); /// /// assert_eq!(v.swap_remove(0), "foo"); - /// assert_eq!(v, vec!["baz", "qux"]); + /// assert_eq!(v, ["baz", "qux"]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -531,9 +531,9 @@ impl Vec { /// ``` /// let mut vec = vec![1, 2, 3]; /// vec.insert(1, 4); - /// assert_eq!(vec, vec![1, 4, 2, 3]); + /// assert_eq!(vec, [1, 4, 2, 3]); /// vec.insert(4, 5); - /// assert_eq!(vec, vec![1, 4, 2, 3, 5]); + /// assert_eq!(vec, [1, 4, 2, 3, 5]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, index: usize, element: T) { @@ -569,7 +569,7 @@ impl Vec { /// ``` /// let mut v = vec![1, 2, 3]; /// assert_eq!(v.remove(1), 2); - /// assert_eq!(v, vec![1, 3]); + /// assert_eq!(v, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, index: usize) -> T { @@ -603,7 +603,7 @@ impl Vec { /// ``` /// let mut vec = vec![1, 2, 3, 4]; /// vec.retain(|&x| x%2 == 0); - /// assert_eq!(vec, vec![2, 4]); + /// assert_eq!(vec, [2, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool { @@ -636,7 +636,7 @@ impl Vec { /// ```rust /// let mut vec = vec!(1, 2); /// vec.push(3); - /// assert_eq!(vec, vec!(1, 2, 3)); + /// assert_eq!(vec, [1, 2, 3]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -674,7 +674,7 @@ impl Vec { /// ```rust /// let mut vec = vec![1, 2, 3]; /// assert_eq!(vec.pop(), Some(3)); - /// assert_eq!(vec, vec![1, 2]); + /// assert_eq!(vec, [1, 2]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -701,8 +701,8 @@ impl Vec { /// let mut vec = vec![1, 2, 3]; /// let mut vec2 = vec![4, 5, 6]; /// vec.append(&mut vec2); - /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]); - /// assert_eq!(vec2, vec![]); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(vec2, []); /// ``` #[inline] #[unstable(feature = "collections", @@ -1019,8 +1019,8 @@ impl Vec { /// ``` /// let mut vec = vec![1,2,3]; /// let vec2 = vec.split_off(1); - /// assert_eq!(vec, vec![1]); - /// assert_eq!(vec2, vec![2, 3]); + /// assert_eq!(vec, [1]); + /// assert_eq!(vec2, [2, 3]); /// ``` #[inline] #[unstable(feature = "collections", @@ -1057,11 +1057,11 @@ impl Vec { /// ``` /// let mut vec = vec!["hello"]; /// vec.resize(3, "world"); - /// assert_eq!(vec, vec!["hello", "world", "world"]); + /// assert_eq!(vec, ["hello", "world", "world"]); /// /// let mut vec = vec![1, 2, 3, 4]; /// vec.resize(2, 0); - /// assert_eq!(vec, vec![1, 2]); + /// assert_eq!(vec, [1, 2]); /// ``` #[unstable(feature = "collections", reason = "matches collection reform specification; waiting for dust to settle")] @@ -1085,7 +1085,7 @@ impl Vec { /// ``` /// let mut vec = vec![1]; /// vec.push_all(&[2, 3, 4]); - /// assert_eq!(vec, vec![1, 2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); /// ``` #[inline] #[unstable(feature = "collections", @@ -1121,7 +1121,7 @@ impl Vec { /// /// vec.dedup(); /// - /// assert_eq!(vec, vec![1, 2, 3, 2]); + /// assert_eq!(vec, [1, 2, 3, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn dedup(&mut self) { @@ -2105,7 +2105,7 @@ mod tests { } } - assert!(values == vec![2, 3, 5, 6, 7]); + assert_eq!(values, [2, 3, 5, 6, 7]); } #[test] @@ -2147,7 +2147,7 @@ mod tests { fn test_retain() { let mut vec = vec![1, 2, 3, 4]; vec.retain(|&x| x % 2 == 0); - assert!(vec == vec![2, 4]); + assert_eq!(vec, [2, 4]); } #[test] @@ -2207,13 +2207,13 @@ mod tests { let a = [1, 2, 3]; let ptr = a.as_ptr(); let b = Vec::from_raw_buf(ptr, 3); - assert_eq!(b, vec![1, 2, 3]); + assert_eq!(b, [1, 2, 3]); // Test on-heap copy-from-buf. let c = vec![1, 2, 3, 4, 5]; let ptr = c.as_ptr(); let d = Vec::from_raw_buf(ptr, 5); - assert_eq!(d, vec![1, 2, 3, 4, 5]); + assert_eq!(d, [1, 2, 3, 4, 5]); } } @@ -2375,7 +2375,7 @@ mod tests { for i in vec { vec2.push(i); } - assert!(vec2 == vec![1, 2, 3]); + assert_eq!(vec2, [1, 2, 3]); } #[test] @@ -2385,7 +2385,7 @@ mod tests { for i in vec.into_iter().rev() { vec2.push(i); } - assert!(vec2 == vec![3, 2, 1]); + assert_eq!(vec2, [3, 2, 1]); } #[test] @@ -2395,7 +2395,7 @@ mod tests { for i in vec { vec2.push(i); } - assert!(vec2 == vec![(), (), ()]); + assert_eq!(vec2, [(), (), ()]); } #[test] @@ -2443,16 +2443,16 @@ mod tests { let mut vec = vec![1, 2, 3]; let mut vec2 = vec![4, 5, 6]; vec.append(&mut vec2); - assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]); - assert_eq!(vec2, vec![]); + assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + assert_eq!(vec2, []); } #[test] fn test_split_off() { let mut vec = vec![1, 2, 3, 4, 5, 6]; let vec2 = vec.split_off(4); - assert_eq!(vec, vec![1, 2, 3, 4]); - assert_eq!(vec2, vec![5, 6]); + assert_eq!(vec, [1, 2, 3, 4]); + assert_eq!(vec2, [5, 6]); } #[bench] diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index f65e644fa52..9476b98eb82 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -2105,7 +2105,7 @@ mod tests { let mut d: VecDeque<_> = (0..5).collect(); d.pop_front(); d.swap(0, 3); - assert_eq!(d.iter().cloned().collect::>(), vec!(4, 2, 3, 1)); + assert_eq!(d.iter().cloned().collect::>(), [4, 2, 3, 1]); } #[test] @@ -2868,17 +2868,17 @@ mod tests { // normal append a.append(&mut b); - assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect(), vec![]); + assert_eq!(a.iter().cloned().collect(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect(), []); // append nothing to something a.append(&mut b); - assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect(), vec![]); + assert_eq!(a.iter().cloned().collect(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect(), []); // append something to nothing b.append(&mut a); - assert_eq!(b.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]); - assert_eq!(a.iter().cloned().collect(), vec![]); + assert_eq!(b.iter().cloned().collect(), [1, 2, 3, 4, 5, 6]); + assert_eq!(a.iter().cloned().collect(), []); } } diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index d92249379fa..1c497c86dfd 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -308,7 +308,7 @@ impl VecMap { /// /// let vec: Vec<(usize, &str)> = map.into_iter().collect(); /// - /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]); + /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_iter(self) -> IntoIter { @@ -425,7 +425,7 @@ impl VecMap { /// /// let vec: Vec<(usize, &str)> = map.drain().collect(); /// - /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]); + /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); /// ``` #[unstable(feature = "collections", reason = "matches collection reform specification, waiting for dust to settle")] @@ -1226,7 +1226,7 @@ mod test_map { let vec: Vec<_> = map.drain().collect(); - assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]); + assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); assert_eq!(map.len(), 0); } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 09089f2d04c..6d8e04d97dd 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -582,8 +582,8 @@ pub trait IteratorExt: Iterator + Sized { /// ``` /// let vec = vec![1, 2, 3, 4]; /// let (even, odd): (Vec<_>, Vec<_>) = vec.into_iter().partition(|&n| n % 2 == 0); - /// assert_eq!(even, vec![2, 4]); - /// assert_eq!(odd, vec![1, 3]); + /// assert_eq!(even, [2, 4]); + /// assert_eq!(odd, [1, 3]); /// ``` #[unstable(feature = "core", reason = "recently added as part of collections reform")] diff --git a/src/libcore/option.rs b/src/libcore/option.rs index abfef72a5db..1ecbd8fae8c 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -556,7 +556,7 @@ impl Option { /// ``` /// let x = Some("string"); /// let v: Vec<&str> = x.into_iter().collect(); - /// assert_eq!(v, vec!["string"]); + /// assert_eq!(v, ["string"]); /// /// let x = None; /// let v: Vec<&str> = x.into_iter().collect(); diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 23e936a75d7..bca73782491 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -548,11 +548,11 @@ impl Result { /// ``` /// let x: Result = Ok(5); /// let v: Vec = x.into_iter().collect(); - /// assert_eq!(v, vec![5]); + /// assert_eq!(v, [5]); /// /// let x: Result = Err("nothing!"); /// let v: Vec = x.into_iter().collect(); - /// assert_eq!(v, vec![]); + /// assert_eq!(v, []); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 6cbc7bf1bbc..8a27400389f 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -74,7 +74,7 @@ fn test_multi_iter() { fn test_counter_from_iter() { let it = count(0, 5).take(10); let xs: Vec = FromIterator::from_iter(it); - assert!(xs == vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); + assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); } #[test] @@ -104,7 +104,7 @@ fn test_iterator_chain() { fn test_filter_map() { let it = count(0, 1).take(10) .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); - assert!(it.collect::>() == vec![0*0, 2*2, 4*4, 6*6, 8*8]); + assert_eq!(it.collect::>(), [0*0, 2*2, 4*4, 6*6, 8*8]); } #[test] @@ -730,12 +730,12 @@ fn test_random_access_cycle() { #[test] fn test_double_ended_range() { - assert!((11..14).rev().collect::>() == vec![13, 12, 11]); + assert_eq!((11..14).rev().collect::>(), [13, 12, 11]); for _ in (10..0).rev() { panic!("unreachable"); } - assert!((11..14).rev().collect::>() == vec![13, 12, 11]); + assert_eq!((11..14).rev().collect::>(), [13, 12, 11]); for _ in (10..0).rev() { panic!("unreachable"); } @@ -743,10 +743,9 @@ fn test_double_ended_range() { #[test] fn test_range() { - assert!((0..5).collect::>() == vec![0, 1, 2, 3, 4]); - assert!((-10..-1).collect::>() == - vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]); - assert!((0..5).rev().collect::>() == vec![4, 3, 2, 1, 0]); + assert_eq!((0..5).collect::>(), [0, 1, 2, 3, 4]); + assert_eq!((-10..-1).collect::>(), [-10, -9, -8, -7, -6, -5, -4, -3, -2]); + assert_eq!((0..5).rev().collect::>(), [4, 3, 2, 1, 0]); assert_eq!((200..-5).count(), 0); assert_eq!((200..-5).rev().count(), 0); assert_eq!((200..200).count(), 0); @@ -767,38 +766,28 @@ fn test_range_inclusive() { vec![5, 4, 3, 2, 1, 0]); assert_eq!(range_inclusive(200, -5).count(), 0); assert_eq!(range_inclusive(200, -5).rev().count(), 0); - assert!(range_inclusive(200, 200).collect::>() == vec![200]); - assert!(range_inclusive(200, 200).rev().collect::>() == vec![200]); + assert_eq!(range_inclusive(200, 200).collect::>(), [200]); + assert_eq!(range_inclusive(200, 200).rev().collect::>(), [200]); } #[test] fn test_range_step() { - assert!(range_step(0, 20, 5).collect::>() == - vec![0, 5, 10, 15]); - assert!(range_step(20, 0, -5).collect::>() == - vec![20, 15, 10, 5]); - assert!(range_step(20, 0, -6).collect::>() == - vec![20, 14, 8, 2]); - assert!(range_step(200u8, 255, 50).collect::>() == - vec![200u8, 250]); - assert!(range_step(200, -5, 1).collect::>() == vec![]); - assert!(range_step(200, 200, 1).collect::>() == vec![]); + assert_eq!(range_step(0, 20, 5).collect::>(), [0, 5, 10, 15]); + assert_eq!(range_step(20, 0, -5).collect::>(), [20, 15, 10, 5]); + assert_eq!(range_step(20, 0, -6).collect::>(), [20, 14, 8, 2]); + assert_eq!(range_step(200u8, 255, 50).collect::>(), [200u8, 250]); + assert_eq!(range_step(200i, -5, 1).collect::>(), []); + assert_eq!(range_step(200i, 200, 1).collect::>(), []); } #[test] fn test_range_step_inclusive() { - assert!(range_step_inclusive(0, 20, 5).collect::>() == - vec![0, 5, 10, 15, 20]); - assert!(range_step_inclusive(20, 0, -5).collect::>() == - vec![20, 15, 10, 5, 0]); - assert!(range_step_inclusive(20, 0, -6).collect::>() == - vec![20, 14, 8, 2]); - assert!(range_step_inclusive(200u8, 255, 50).collect::>() == - vec![200u8, 250]); - assert!(range_step_inclusive(200, -5, 1).collect::>() == - vec![]); - assert!(range_step_inclusive(200, 200, 1).collect::>() == - vec![200]); + assert_eq!(range_step_inclusive(0, 20, 5).collect::>(), [0, 5, 10, 15, 20]); + assert_eq!(range_step_inclusive(20, 0, -5).collect::>(), [20, 15, 10, 5, 0]); + assert_eq!(range_step_inclusive(20, 0, -6).collect::>(), [20, 14, 8, 2]); + assert_eq!(range_step_inclusive(200u8, 255, 50).collect::>(), [200u8, 250]); + assert_eq!(range_step_inclusive(200, -5, 1).collect::>(), []); + assert_eq!(range_step_inclusive(200, 200, 1).collect::>(), [200]); } #[test] diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs index 5aeb330b78b..73000670c61 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -103,7 +103,7 @@ fn test_transmute() { } unsafe { - assert!(vec![76u8] == transmute::<_, Vec>("L".to_string())); + assert_eq!([76u8], transmute::<_, Vec>("L".to_string())); } } diff --git a/src/libcoretest/nonzero.rs b/src/libcoretest/nonzero.rs index be4c83d23e8..f60570eaaf4 100644 --- a/src/libcoretest/nonzero.rs +++ b/src/libcoretest/nonzero.rs @@ -54,7 +54,7 @@ fn test_match_option_empty_vec() { fn test_match_option_vec() { let a = Some(vec![1, 2, 3, 4]); match a { - Some(v) => assert_eq!(v, vec![1, 2, 3, 4]), + Some(v) => assert_eq!(v, [1, 2, 3, 4]), None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])") } } diff --git a/src/libcoretest/ptr.rs b/src/libcoretest/ptr.rs index 57456bfb1a7..c8a54ef59ab 100644 --- a/src/libcoretest/ptr.rs +++ b/src/libcoretest/ptr.rs @@ -156,7 +156,7 @@ fn test_ptr_subtraction() { m_ptr = m_ptr.offset(-1); } - assert!(xs_mut == vec![0,2,4,6,8,10,12,14,16,18]); + assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]); } } diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index beb746d25b6..019f935911f 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -22,7 +22,7 @@ fn test_pattern_deref_forward() { fn test_empty_match_indices() { let data = "aä中!"; let vec: Vec<_> = data.match_indices("").collect(); - assert_eq!(vec, vec![(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]); + assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]); } #[test] @@ -69,20 +69,20 @@ fn test_rsplitn_char_iterator() { let mut split: Vec<&str> = data.rsplitn(3, ' ').collect(); split.reverse(); - assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect(); split.reverse(); - assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); // Unicode let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect(); split.reverse(); - assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect(); split.reverse(); - assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); } #[test] @@ -90,33 +90,33 @@ fn test_split_char_iterator() { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; let split: Vec<&str> = data.split(' ').collect(); - assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); let mut rsplit: Vec<&str> = data.split(' ').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); let split: Vec<&str> = data.split(|c: char| c == ' ').collect(); - assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); // Unicode let split: Vec<&str> = data.split('ä').collect(); - assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); let mut rsplit: Vec<&str> = data.split('ä').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); let split: Vec<&str> = data.split(|c: char| c == 'ä').collect(); - assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); } #[test] @@ -125,18 +125,18 @@ fn test_rev_split_char_iterator_no_trailing() { let mut split: Vec<&str> = data.split('\n').rev().collect(); split.reverse(); - assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); let mut split: Vec<&str> = data.split_terminator('\n').rev().collect(); split.reverse(); - assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); } #[test] fn test_utf16_code_units() { use unicode::str::Utf16Encoder; assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::>(), - vec![0xE9, 0xD83D, 0xDCA9]) + [0xE9, 0xD83D, 0xDCA9]) } #[test] diff --git a/src/librbml/io.rs b/src/librbml/io.rs index 230fda11ab5..c52465a8899 100644 --- a/src/librbml/io.rs +++ b/src/librbml/io.rs @@ -45,7 +45,7 @@ fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult /// let mut w = SeekableMemWriter::new(); /// w.write(&[0, 1, 2]); /// -/// assert_eq!(w.unwrap(), vec!(0, 1, 2)); +/// assert_eq!(w.unwrap(), [0, 1, 2]); /// ``` pub struct SeekableMemWriter { buf: Vec, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index cdcc9850e42..d9cedc48298 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -806,11 +806,11 @@ fn walk_ty() { let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty)); let uniq_ty = ty::mk_uniq(tcx, tup2_ty); let walked: Vec<_> = uniq_ty.walk().collect(); - assert_eq!(vec!(uniq_ty, - tup2_ty, - tup1_ty, int_ty, uint_ty, int_ty, uint_ty, - tup1_ty, int_ty, uint_ty, int_ty, uint_ty, - uint_ty), + assert_eq!([uniq_ty, + tup2_ty, + tup1_ty, int_ty, uint_ty, int_ty, uint_ty, + tup1_ty, int_ty, uint_ty, int_ty, uint_ty, + uint_ty], walked); }) } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index a0f42815b43..05d4e0f59fe 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -3074,19 +3074,19 @@ mod tests { #[test] fn test_decode_array() { let v: Vec<()> = super::decode("[]").unwrap(); - assert_eq!(v, vec![]); + assert_eq!(v, []); let v: Vec<()> = super::decode("[null]").unwrap(); - assert_eq!(v, vec![()]); + assert_eq!(v, [()]); let v: Vec = super::decode("[true]").unwrap(); - assert_eq!(v, vec![true]); + assert_eq!(v, [true]); let v: Vec = super::decode("[3, 1]").unwrap(); - assert_eq!(v, vec![3, 1]); + assert_eq!(v, [3, 1]); let v: Vec> = super::decode("[[3], [1, 2]]").unwrap(); - assert_eq!(v, vec![vec![3], vec![1, 2]]); + assert_eq!(v, [vec![3], vec![1, 2]]); } #[test] diff --git a/src/libstd/old_io/extensions.rs b/src/libstd/old_io/extensions.rs index c2a6c515acc..8bd19f063f0 100644 --- a/src/libstd/old_io/extensions.rs +++ b/src/libstd/old_io/extensions.rs @@ -328,7 +328,7 @@ mod test { fn read_bytes() { let mut reader = MemReader::new(vec!(10, 11, 12, 13)); let bytes = reader.read_exact(4).unwrap(); - assert!(bytes == vec!(10, 11, 12, 13)); + assert_eq!(bytes, [10, 11, 12, 13]); } #[test] @@ -337,7 +337,7 @@ mod test { count: 0, }; let bytes = reader.read_exact(4).unwrap(); - assert!(bytes == vec!(10, 11, 12, 13)); + assert_eq!(bytes, [10, 11, 12, 13]); } #[test] @@ -351,7 +351,7 @@ mod test { let mut reader = MemReader::new(vec![10, 11, 12, 13]); let mut buf = vec![8, 9]; assert!(reader.push_at_least(4, 4, &mut buf).is_ok()); - assert!(buf == vec![8, 9, 10, 11, 12, 13]); + assert_eq!(buf, [8, 9, 10, 11, 12, 13]); } #[test] @@ -361,7 +361,7 @@ mod test { }; let mut buf = vec![8, 9]; assert!(reader.push_at_least(4, 4, &mut buf).is_ok()); - assert!(buf == vec![8, 9, 10, 11, 12, 13]); + assert_eq!(buf, [8, 9, 10, 11, 12, 13]); } #[test] @@ -369,7 +369,7 @@ mod test { let mut reader = MemReader::new(vec![10, 11]); let mut buf = vec![8, 9]; assert!(reader.push_at_least(4, 4, &mut buf).is_err()); - assert!(buf == vec![8, 9, 10, 11]); + assert_eq!(buf, [8, 9, 10, 11]); } #[test] @@ -379,7 +379,7 @@ mod test { }; let mut buf = vec![8, 9]; assert!(reader.push_at_least(4, 4, &mut buf).is_err()); - assert!(buf == vec![8, 9, 10]); + assert_eq!(buf, [8, 9, 10]); } #[test] @@ -388,7 +388,7 @@ mod test { count: 0, }; let buf = reader.read_to_end().unwrap(); - assert!(buf == vec!(10, 11, 12, 13)); + assert_eq!(buf, [10, 11, 12, 13]); } #[test] @@ -398,7 +398,7 @@ mod test { count: 0, }; let buf = reader.read_to_end().unwrap(); - assert!(buf == vec!(10, 11)); + assert_eq!(buf, [10, 11]); } #[test] diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs index 1fd527014a3..c08a2c1f477 100644 --- a/src/libstd/old_io/mem.rs +++ b/src/libstd/old_io/mem.rs @@ -60,7 +60,7 @@ impl Writer for Vec { /// let mut w = MemWriter::new(); /// w.write(&[0, 1, 2]); /// -/// assert_eq!(w.into_inner(), vec!(0, 1, 2)); +/// assert_eq!(w.into_inner(), [0, 1, 2]); /// ``` #[unstable(feature = "io")] #[deprecated(since = "1.0.0", @@ -118,7 +118,7 @@ impl Writer for MemWriter { /// /// let mut r = MemReader::new(vec!(0, 1, 2)); /// -/// assert_eq!(r.read_to_end().unwrap(), vec!(0, 1, 2)); +/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]); /// ``` pub struct MemReader { buf: Vec, @@ -321,7 +321,7 @@ impl<'a> Seek for BufWriter<'a> { /// let buf = [0, 1, 2, 3]; /// let mut r = BufReader::new(&buf); /// -/// assert_eq!(r.read_to_end().unwrap(), vec![0, 1, 2, 3]); +/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2, 3]); /// ``` pub struct BufReader<'a> { buf: &'a [u8], @@ -504,8 +504,8 @@ mod test { assert_eq!(&buf[..3], b); assert!(reader.read(&mut buf).is_err()); let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); - assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3)); - assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7)); + assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]); + assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]); assert!(reader.read(&mut buf).is_err()); } @@ -530,8 +530,8 @@ mod test { assert_eq!(&buf[..3], b); assert!(reader.read(&mut buf).is_err()); let mut reader = &mut &*in_buf; - assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3)); - assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7)); + assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]); + assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]); assert!(reader.read(&mut buf).is_err()); } @@ -557,8 +557,8 @@ mod test { assert_eq!(&buf[..3], b); assert!(reader.read(&mut buf).is_err()); let mut reader = BufReader::new(&in_buf); - assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3)); - assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7)); + assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]); + assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]); assert!(reader.read(&mut buf).is_err()); } diff --git a/src/libstd/old_io/result.rs b/src/libstd/old_io/result.rs index f42cb6ce8c9..cdf2bae1cba 100644 --- a/src/libstd/old_io/result.rs +++ b/src/libstd/old_io/result.rs @@ -87,7 +87,7 @@ mod test { let mut writer: old_io::IoResult> = Ok(Vec::new()); writer.write_all(&[0, 1, 2]).unwrap(); writer.flush().unwrap(); - assert_eq!(writer.unwrap(), vec!(0, 1, 2)); + assert_eq!(writer.unwrap(), [0, 1, 2]); } #[test] diff --git a/src/libstd/old_io/util.rs b/src/libstd/old_io/util.rs index 5ae239014d1..8e49335ed54 100644 --- a/src/libstd/old_io/util.rs +++ b/src/libstd/old_io/util.rs @@ -284,7 +284,7 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2)); { let mut r = LimitReader::new(r.by_ref(), 4); - assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap()); + assert_eq!([0, 1, 2], r.read_to_end().unwrap()); } } @@ -293,9 +293,9 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2)); { let mut r = LimitReader::new(r.by_ref(), 2); - assert_eq!(vec!(0, 1), r.read_to_end().unwrap()); + assert_eq!([0, 1], r.read_to_end().unwrap()); } - assert_eq!(vec!(2), r.read_to_end().unwrap()); + assert_eq!([2], r.read_to_end().unwrap()); } #[test] @@ -305,7 +305,7 @@ mod test { assert_eq!(3, r.limit()); assert_eq!(0, r.read_byte().unwrap()); assert_eq!(2, r.limit()); - assert_eq!(vec!(1, 2), r.read_to_end().unwrap()); + assert_eq!([1, 2], r.read_to_end().unwrap()); assert_eq!(0, r.limit()); } @@ -314,7 +314,7 @@ mod test { let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]); let mut r = LimitReader::new(r.by_ref(), 1); r.consume(2); - assert_eq!(vec![], r.read_to_end().unwrap()); + assert_eq!([], r.read_to_end().unwrap()); } #[test] @@ -330,7 +330,7 @@ mod test { let mut s = ZeroReader; let mut buf = vec![1, 2, 3]; assert_eq!(s.read(&mut buf), Ok(3)); - assert_eq!(vec![0, 0, 0], buf); + assert_eq!([0, 0, 0], buf); } #[test] @@ -373,16 +373,16 @@ mod test { let rs = vec!(MemReader::new(vec!(0, 1)), MemReader::new(vec!()), MemReader::new(vec!(2, 3))); let mut r = ChainedReader::new(rs.into_iter()); - assert_eq!(vec!(0, 1, 2, 3), r.read_to_end().unwrap()); + assert_eq!([0, 1, 2, 3], r.read_to_end().unwrap()); } #[test] fn test_tee_reader() { let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)), Vec::new()); - assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap()); + assert_eq!([0, 1, 2], r.read_to_end().unwrap()); let (_, w) = r.into_inner(); - assert_eq!(vec!(0, 1, 2), w); + assert_eq!([0, 1, 2], w); } #[test] @@ -390,7 +390,7 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2, 3, 4)); let mut w = Vec::new(); copy(&mut r, &mut w).unwrap(); - assert_eq!(vec!(0, 1, 2, 3, 4), w); + assert_eq!([0, 1, 2, 3, 4], w); } #[test] diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 9119a3c60d8..fb9d6fef1fa 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -1202,11 +1202,11 @@ mod tests { string.code_points().map(|c| c.to_char()).collect::>() } let mut string = Wtf8Buf::from_str("é "); - assert_eq!(cp(&string), vec![Some('é'), Some(' ')]); + assert_eq!(cp(&string), [Some('é'), Some(' ')]); string.push(c(0xD83D)); - assert_eq!(cp(&string), vec![Some('é'), Some(' '), None]); + assert_eq!(cp(&string), [Some('é'), Some(' '), None]); string.push(c(0xDCA9)); - assert_eq!(cp(&string), vec![Some('é'), Some(' '), Some('💩')]); + assert_eq!(cp(&string), [Some('é'), Some(' '), Some('💩')]); } #[test] diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index bc239d0c7c2..91bfe6f32dc 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -2028,7 +2028,7 @@ foo_module!(); let renamed_crate = renamer.fold_crate(the_crate); let idents = crate_idents(&renamed_crate); let resolved : Vec = idents.iter().map(|id| mtwt::resolve(*id)).collect(); - assert_eq!(resolved,vec!(f_ident.name,Name(16),int_ident.name,Name(16),Name(16),Name(16))); + assert_eq!(resolved, [f_ident.name,Name(16),int_ident.name,Name(16),Name(16),Name(16)]); } // test the PatIdentRenamer; only PatIdents get renamed @@ -2044,8 +2044,6 @@ foo_module!(); let idents = crate_idents(&renamed_crate); let resolved : Vec = idents.iter().map(|id| mtwt::resolve(*id)).collect(); let x_name = x_ident.name; - assert_eq!(resolved,vec!(f_ident.name,Name(16),int_ident.name,Name(16),x_name,x_name)); + assert_eq!(resolved, [f_ident.name,Name(16),int_ident.name,Name(16),x_name,x_name]); } - - } diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index b6563d77b88..72431d8e6aa 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -288,19 +288,19 @@ mod tests { fn xorpush_test () { let mut s = Vec::new(); xor_push(&mut s, 14); - assert_eq!(s.clone(), vec!(14)); + assert_eq!(s.clone(), [14]); xor_push(&mut s, 14); - assert_eq!(s.clone(), Vec::new()); + assert_eq!(s.clone(), []); xor_push(&mut s, 14); - assert_eq!(s.clone(), vec!(14)); + assert_eq!(s.clone(), [14]); xor_push(&mut s, 15); - assert_eq!(s.clone(), vec!(14, 15)); + assert_eq!(s.clone(), [14, 15]); xor_push(&mut s, 16); - assert_eq!(s.clone(), vec!(14, 15, 16)); + assert_eq!(s.clone(), [14, 15, 16]); xor_push(&mut s, 16); - assert_eq!(s.clone(), vec!(14, 15)); + assert_eq!(s.clone(), [14, 15]); xor_push(&mut s, 15); - assert_eq!(s.clone(), vec!(14)); + assert_eq!(s.clone(), [14]); } fn id(n: u32, s: SyntaxContext) -> Ident { @@ -389,13 +389,13 @@ mod tests { assert_eq!(marksof_internal (EMPTY_CTXT,stopname,&t),Vec::new()); // FIXME #5074: ANF'd to dodge nested calls { let ans = unfold_marks(vec!(4,98),EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans,stopname,&t),vec!(4,98));} + assert_eq! (marksof_internal (ans,stopname,&t), [4, 98]);} // does xoring work? { let ans = unfold_marks(vec!(5,5,16),EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans,stopname,&t), vec!(16));} + assert_eq! (marksof_internal (ans,stopname,&t), [16]);} // does nested xoring work? { let ans = unfold_marks(vec!(5,10,10,5,16),EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans, stopname,&t), vec!(16));} + assert_eq! (marksof_internal (ans, stopname,&t), [16]);} // rename where stop doesn't match: { let chain = vec!(M(9), R(id(name1.usize() as u32, @@ -403,7 +403,7 @@ mod tests { Name(100101102)), M(14)); let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans, stopname, &t), vec!(9,14));} + assert_eq! (marksof_internal (ans, stopname, &t), [9, 14]);} // rename where stop does match { let name1sc = apply_mark_internal(4, EMPTY_CTXT, &mut t); let chain = vec!(M(9), @@ -411,7 +411,7 @@ mod tests { stopname), M(14)); let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans, stopname, &t), vec!(9)); } + assert_eq! (marksof_internal (ans, stopname, &t), [9]); } } diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index 0a39d380904..90df23882a1 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -229,10 +229,10 @@ mod test { assert_eq!(Vec::new(), v); let v = SmallVector::one(1); - assert_eq!(vec![1], v.into_iter().collect::>()); + assert_eq!([1], v.into_iter().collect::>()); let v = SmallVector::many(vec![1, 2, 3]); - assert_eq!(vec!(1, 2, 3), v.into_iter().collect::>()); + assert_eq!([1, 2, 3], v.into_iter().collect::>()); } #[test] diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs index 0b577f8de74..112525fcce9 100644 --- a/src/libterm/terminfo/parm.rs +++ b/src/libterm/terminfo/parm.rs @@ -652,15 +652,15 @@ mod test { let s = format!("%{{1}}%{{2}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); assert!(res.is_ok(), res.err().unwrap()); - assert_eq!(res.unwrap(), vec!(b'0' + bs[0])); + assert_eq!(res.unwrap(), [b'0' + bs[0]]); let s = format!("%{{1}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); assert!(res.is_ok(), res.err().unwrap()); - assert_eq!(res.unwrap(), vec!(b'0' + bs[1])); + assert_eq!(res.unwrap(), [b'0' + bs[1]]); let s = format!("%{{2}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); assert!(res.is_ok(), res.err().unwrap()); - assert_eq!(res.unwrap(), vec!(b'0' + bs[2])); + assert_eq!(res.unwrap(), [b'0' + bs[2]]); } } diff --git a/src/test/run-pass/auto-ref-sliceable.rs b/src/test/run-pass/auto-ref-sliceable.rs index 652f21c2ae3..d2e9bc2efe7 100644 --- a/src/test/run-pass/auto-ref-sliceable.rs +++ b/src/test/run-pass/auto-ref-sliceable.rs @@ -23,5 +23,5 @@ pub fn main() { let mut v = vec!(1); v.push_val(2); v.push_val(3); - assert_eq!(v, vec!(1, 2, 3)); + assert_eq!(v, [1, 2, 3]); } diff --git a/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs b/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs index f87f2e07c9d..2473b4b674e 100644 --- a/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs +++ b/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs @@ -22,5 +22,5 @@ fn bar(v: &mut [uint]) { pub fn main() { let mut the_vec = vec!(1, 2, 3, 100); bar(&mut the_vec); - assert_eq!(the_vec, vec!(100, 3, 2, 1)); + assert_eq!(the_vec, [100, 3, 2, 1]); } diff --git a/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs b/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs index 4f97e6a2081..ea09bb3904d 100644 --- a/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs @@ -18,5 +18,5 @@ fn bar(v: &mut [uint]) { pub fn main() { let mut the_vec = vec!(1, 2, 3, 100); bar(&mut the_vec); - assert_eq!(the_vec, vec!(100, 3, 2, 1)); + assert_eq!(the_vec, [100, 3, 2, 1]); } diff --git a/src/test/run-pass/generic-static-methods.rs b/src/test/run-pass/generic-static-methods.rs index 7f84efcdd5d..010f54dd559 100644 --- a/src/test/run-pass/generic-static-methods.rs +++ b/src/test/run-pass/generic-static-methods.rs @@ -24,5 +24,5 @@ impl vec_utils for Vec { } pub fn main() { - assert_eq!(vec_utils::map_(&vec!(1,2,3), |&x| x+1), vec!(2,3,4)); + assert_eq!(vec_utils::map_(&vec!(1,2,3), |&x| x+1), [2,3,4]); } diff --git a/src/test/run-pass/monad.rs b/src/test/run-pass/monad.rs index 457c0a35fd7..0d563f1a714 100644 --- a/src/test/run-pass/monad.rs +++ b/src/test/run-pass/monad.rs @@ -44,11 +44,11 @@ fn transform(x: Option) -> Option { pub fn main() { assert_eq!(transform(Some(10)), Some("11".to_string())); assert_eq!(transform(None), None); - assert!((vec!("hi".to_string())) + assert_eq!((vec!("hi".to_string())) .bind(|x| vec!(x.clone(), format!("{}!", x)) ) - .bind(|x| vec!(x.clone(), format!("{}?", x)) ) == - vec!("hi".to_string(), - "hi?".to_string(), - "hi!".to_string(), - "hi!?".to_string())); + .bind(|x| vec!(x.clone(), format!("{}?", x)) ), + ["hi".to_string(), + "hi?".to_string(), + "hi!".to_string(), + "hi!?".to_string()]); } diff --git a/src/test/run-pass/trait-generic.rs b/src/test/run-pass/trait-generic.rs index 5f4b18df6e1..0dedf621a4f 100644 --- a/src/test/run-pass/trait-generic.rs +++ b/src/test/run-pass/trait-generic.rs @@ -44,9 +44,9 @@ fn bar>(x: T) -> Vec { } pub fn main() { - assert_eq!(foo(vec!(1)), vec!("hi".to_string())); - assert_eq!(bar:: >(vec!(4, 5)), vec!("4".to_string(), "5".to_string())); + assert_eq!(foo(vec!(1)), ["hi".to_string()]); + assert_eq!(bar:: >(vec!(4, 5)), ["4".to_string(), "5".to_string()]); assert_eq!(bar:: >(vec!("x".to_string(), "y".to_string())), - vec!("x".to_string(), "y".to_string())); - assert_eq!(bar::<(), Vec<()>>(vec!(())), vec!("()".to_string())); + ["x".to_string(), "y".to_string()]); + assert_eq!(bar::<(), Vec<()>>(vec!(())), ["()".to_string()]); } diff --git a/src/test/run-pass/unboxed-closures-infer-upvar.rs b/src/test/run-pass/unboxed-closures-infer-upvar.rs index 087ef5dcf05..1401fe7470b 100644 --- a/src/test/run-pass/unboxed-closures-infer-upvar.rs +++ b/src/test/run-pass/unboxed-closures-infer-upvar.rs @@ -18,5 +18,5 @@ fn f(mut f: F) { fn main() { let mut v: Vec<_> = vec![]; f(|| v.push(0)); - assert_eq!(v, vec![0]); + assert_eq!(v, [0]); } -- cgit 1.4.1-3-g733a5 From 2d200c9c8bd6659720a68ab8dd74218b1e58c1e9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Feb 2015 10:59:17 -0800 Subject: std: Move std::env to the new I/O APIs This commit moves `std::env` away from the `std::old_io` error type as well as the `std::old_path` module. Methods returning an error now return `io::Error` and methods consuming or returning paths use `std::path` instead of `std::old_path`. This commit does not yet mark these APIs as `#[stable]`. This commit also migrates `std::old_io::TempDir` to `std::fs::TempDir` with essentially the exact same API. This type was added to interoperate with the new path API and has its own `tempdir` feature. Finally, this commit reverts the deprecation of `std::os` APIs returning the old path API types. This deprecation can come back once the entire `std::old_path` module is deprecated. [breaking-change] --- src/librustc/lib.rs | 1 + src/librustc/metadata/filesearch.rs | 7 +- src/librustc/plugin/load.rs | 4 +- src/librustc/session/mod.rs | 6 +- src/librustc_back/archive.rs | 6 +- src/librustc_back/fs.rs | 4 +- src/librustc_back/lib.rs | 1 + src/librustc_back/rpath.rs | 6 +- src/librustc_back/target/mod.rs | 3 +- src/librustc_driver/driver.rs | 5 +- src/librustdoc/test.rs | 6 +- src/libstd/dynamic_lib.rs | 3 +- src/libstd/env.rs | 27 +- src/libstd/fs.rs | 1503 ---------------------------------- src/libstd/fs/mod.rs | 1507 +++++++++++++++++++++++++++++++++++ src/libstd/fs/tempdir.rs | 125 +++ src/libstd/net/test.rs | 2 +- src/libstd/old_io/tempfile.rs | 6 +- src/libstd/old_io/test.rs | 5 +- src/libstd/os.rs | 55 +- src/libstd/sys/unix/backtrace.rs | 5 +- src/libstd/sys/unix/os.rs | 57 +- src/libstd/sys/windows/fs.rs | 4 +- src/libstd/sys/windows/mod.rs | 14 +- src/libstd/sys/windows/os.rs | 36 +- src/libstd/sys/windows/process2.rs | 10 +- src/libterm/lib.rs | 1 + src/libterm/terminfo/searcher.rs | 3 +- src/test/run-pass/env-home-dir.rs | 3 +- src/test/run-pass/issue-15149.rs | 32 +- src/test/run-pass/issue-16272.rs | 6 +- src/test/run-pass/issue-20091.rs | 17 +- 32 files changed, 1826 insertions(+), 1644 deletions(-) delete mode 100644 src/libstd/fs.rs create mode 100644 src/libstd/fs/mod.rs create mode 100644 src/libstd/fs/tempdir.rs (limited to 'src/libstd/sys') diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index fe9a81bb7c9..26cb4f917c5 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -40,6 +40,7 @@ #![feature(staged_api)] #![feature(std_misc)] #![feature(unicode)] +#![feature(os)] #![cfg_attr(test, feature(test))] extern crate arena; diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index d63b3dd60d0..a8d39f95739 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -14,6 +14,7 @@ pub use self::FileMatch::*; use std::collections::HashSet; use std::env; +use std::os; use std::old_io::fs::PathExtensions; use std::old_io::fs; @@ -194,7 +195,7 @@ pub fn get_or_default_sysroot() -> Path { }) } - match canonicalize(env::current_exe().ok()) { + match canonicalize(os::self_exe_name()) { Some(mut p) => { p.pop(); p.pop(); p } None => panic!("can't determine value for sysroot") } @@ -224,7 +225,7 @@ pub fn rust_path() -> Vec { } None => Vec::new() }; - let mut cwd = env::current_dir().unwrap(); + let mut cwd = os::getcwd().unwrap(); // now add in default entries let cwd_dot_rust = cwd.join(".rust"); if !env_rust_path.contains(&cwd_dot_rust) { @@ -243,7 +244,7 @@ pub fn rust_path() -> Vec { } cwd.pop(); } - if let Some(h) = env::home_dir() { + if let Some(h) = os::homedir() { let p = h.join(".rust"); if !env_rust_path.contains(&p) && p.exists() { env_rust_path.push(p); diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index b3bc898748f..a419d4134b4 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -15,7 +15,7 @@ use metadata::creader::CrateReader; use plugin::registry::Registry; use std::mem; -use std::env; +use std::os; use std::dynamic_lib::DynamicLibrary; use std::borrow::ToOwned; use syntax::ast; @@ -103,7 +103,7 @@ impl<'a> PluginLoader<'a> { path: Path, symbol: String) -> PluginRegistrarFun { // Make sure the path contains a / or the linker will search for it. - let path = env::current_dir().unwrap().join(&path); + let path = os::getcwd().unwrap().join(&path); let lib = match DynamicLibrary::open(Some(&path)) { Ok(lib) => lib, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index b690cc7f7d0..615ee77c1e0 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -27,8 +27,8 @@ use syntax::{ast, codemap}; use rustc_back::target::Target; -use std::env; use std::cell::{Cell, RefCell}; +use std::os; pub mod config; pub mod search_paths; @@ -347,7 +347,7 @@ pub fn build_session_(sopts: config::Options, if path.is_absolute() { path.clone() } else { - env::current_dir().unwrap().join(&path) + os::getcwd().unwrap().join(&path) } ); @@ -370,7 +370,7 @@ pub fn build_session_(sopts: config::Options, plugin_registrar_fn: Cell::new(None), default_sysroot: default_sysroot, local_crate_source_file: local_crate_source_file, - working_dir: env::current_dir().unwrap(), + working_dir: os::getcwd().unwrap(), lint_store: RefCell::new(lint::LintStore::new()), lints: RefCell::new(NodeMap()), crate_types: RefCell::new(Vec::new()), diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index 6bf745315ea..3fcae6a8034 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -14,7 +14,7 @@ use std::old_io::fs::PathExtensions; use std::old_io::process::{Command, ProcessOutput}; use std::old_io::{fs, TempDir}; use std::old_io; -use std::env; +use std::os; use std::str; use syntax::diagnostic::Handler as ErrorHandler; @@ -224,7 +224,7 @@ impl<'a> ArchiveBuilder<'a> { pub fn build(self) -> Archive<'a> { // Get an absolute path to the destination, so `ar` will work even // though we run it from `self.work_dir`. - let abs_dst = env::current_dir().unwrap().join(&self.archive.dst); + let abs_dst = os::getcwd().unwrap().join(&self.archive.dst); assert!(!abs_dst.is_relative()); let mut args = vec![&abs_dst]; let mut total_len = abs_dst.as_vec().len(); @@ -283,7 +283,7 @@ impl<'a> ArchiveBuilder<'a> { // First, extract the contents of the archive to a temporary directory. // We don't unpack directly into `self.work_dir` due to the possibility // of filename collisions. - let archive = env::current_dir().unwrap().join(archive); + let archive = os::getcwd().unwrap().join(archive); run_ar(self.archive.handler, &self.archive.maybe_ar_prog, "x", Some(loc.path()), &[&archive]); diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs index acf49d1ca46..99a1df95a80 100644 --- a/src/librustc_back/fs.rs +++ b/src/librustc_back/fs.rs @@ -10,13 +10,13 @@ use std::old_io; use std::old_io::fs; -use std::env; +use std::os; /// Returns an absolute path in the filesystem that `path` points to. The /// returned path does not contain any symlinks in its hierarchy. pub fn realpath(original: &Path) -> old_io::IoResult { static MAX_LINKS_FOLLOWED: uint = 256; - let original = try!(env::current_dir()).join(original); + let original = try!(os::getcwd()).join(original); // Right now lstat on windows doesn't work quite well if cfg!(windows) { diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index d589b063204..711f937d2f3 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -41,6 +41,7 @@ #![feature(rustc_private)] #![feature(staged_api)] #![feature(env)] +#![feature(path)] extern crate syntax; extern crate serialize; diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index 3f2dcee5110..943ff52925a 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use std::collections::HashSet; use std::env; use std::old_io::IoError; +use std::os; use syntax::ast; pub struct RPathConfig where @@ -109,7 +109,7 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path "$ORIGIN" }; - let cwd = env::current_dir().unwrap(); + let cwd = os::getcwd().unwrap(); let mut lib = (config.realpath)(&cwd.join(lib)).unwrap(); lib.pop(); let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap(); @@ -129,7 +129,7 @@ fn get_install_prefix_rpath(config: RPathConfig) -> String where let path = (config.get_install_prefix_lib_path)(); let path = env::current_dir().unwrap().join(&path); // FIXME (#9639): This needs to handle non-utf8 paths - path.as_str().expect("non-utf8 component in rpath").to_string() + path.to_str().expect("non-utf8 component in rpath").to_string() } fn minimize_rpaths(rpaths: &[String]) -> Vec { diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index b04c07977c3..d09a7c355d3 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -310,6 +310,7 @@ impl Target { /// JSON decoding. pub fn search(target: &str) -> Result { use std::env; + use std::os; use std::ffi::OsString; use std::old_io::File; use std::old_path::Path; @@ -396,7 +397,7 @@ impl Target { // FIXME 16351: add a sane default search path? - for dir in env::split_paths(&target_path) { + for dir in os::split_paths(target_path.to_str().unwrap()).iter() { let p = dir.join(path.clone()); if p.is_file() { return load_file(&p); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b12f05d7c50..a1a0e71f334 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -32,6 +32,7 @@ use super::Compilation; use serialize::json; use std::env; +use std::os; use std::ffi::OsString; use std::old_io::fs; use std::old_io; @@ -471,7 +472,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, if cfg!(windows) { _old_path = env::var_os("PATH").unwrap_or(_old_path); let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths(); - new_path.extend(env::split_paths(&_old_path)); + new_path.extend(os::split_paths(_old_path.to_str().unwrap()).into_iter()); env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap()); } let features = sess.features.borrow(); @@ -738,7 +739,7 @@ pub fn phase_6_link_output(sess: &Session, outputs: &OutputFilenames) { let old_path = env::var_os("PATH").unwrap_or(OsString::from_str("")); let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(); - new_path.extend(env::split_paths(&old_path)); + new_path.extend(os::split_paths(old_path.to_str().unwrap()).into_iter()); env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap()); time(sess.time_passes(), "linking", (), |_| diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index bf14b86ebd1..78f126dcf6a 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -13,7 +13,7 @@ use std::sync::mpsc::channel; use std::dynamic_lib::DynamicLibrary; use std::old_io::{Command, TempDir}; use std::old_io; -use std::env; +use std::os; use std::str; use std::thread; use std::thunk::Thunk; @@ -46,7 +46,7 @@ pub fn run(input: &str, let input = config::Input::File(input_path.clone()); let sessopts = config::Options { - maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()), + maybe_sysroot: Some(os::self_exe_name().unwrap().dir_path().dir_path()), search_paths: libs.clone(), crate_types: vec!(config::CrateTypeDylib), externs: externs.clone(), @@ -113,7 +113,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, let input = config::Input::Str(test.to_string()); let sessopts = config::Options { - maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()), + maybe_sysroot: Some(os::self_exe_name().unwrap().dir_path().dir_path()), search_paths: libs, crate_types: vec!(config::CrateTypeExecutable), output_types: vec!(config::OutputTypeExe), diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index fcae8e79160..babae3b3019 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -21,6 +21,7 @@ use ffi::CString; use mem; use env; use str; +use os; pub struct DynamicLibrary { handle: *mut u8 @@ -102,7 +103,7 @@ impl DynamicLibrary { /// process pub fn search_path() -> Vec { match env::var_os(DynamicLibrary::envvar()) { - Some(var) => env::split_paths(&var).collect(), + Some(var) => os::split_paths(var.to_str().unwrap()), None => Vec::new(), } } diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 0e1f5f2ba02..5db9f6ef7fd 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -21,7 +21,8 @@ use prelude::v1::*; use error::Error; use ffi::{OsString, AsOsStr}; use fmt; -use old_io::IoResult; +use io; +use path::{AsPath, PathBuf}; use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering}; use sync::{StaticMutex, MUTEX_INIT}; use sys::os as os_imp; @@ -46,7 +47,7 @@ use sys::os as os_imp; /// let p = env::current_dir().unwrap(); /// println!("The current directory is {}", p.display()); /// ``` -pub fn current_dir() -> IoResult { +pub fn current_dir() -> io::Result { os_imp::getcwd() } @@ -57,14 +58,14 @@ pub fn current_dir() -> IoResult { /// /// ```rust /// use std::env; -/// use std::old_path::Path; +/// use std::path::Path; /// /// let root = Path::new("/"); /// assert!(env::set_current_dir(&root).is_ok()); /// println!("Successfully changed working directory to {}!", root.display()); /// ``` -pub fn set_current_dir(p: &Path) -> IoResult<()> { - os_imp::chdir(p) +pub fn set_current_dir(p: &P) -> io::Result<()> { + os_imp::chdir(p.as_path()) } static ENV_LOCK: StaticMutex = MUTEX_INIT; @@ -280,8 +281,8 @@ pub fn split_paths(unparsed: &T) -> SplitPaths { } impl<'a> Iterator for SplitPaths<'a> { - type Item = Path; - fn next(&mut self) -> Option { self.inner.next() } + type Item = PathBuf; + fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } @@ -305,10 +306,11 @@ pub struct JoinPathsError { /// /// ```rust /// use std::env; +/// use std::path::PathBuf; /// /// if let Some(path) = env::var_os("PATH") { /// let mut paths = env::split_paths(&path).collect::>(); -/// paths.push(Path::new("/home/xyz/bin")); +/// paths.push(PathBuf::new("/home/xyz/bin")); /// let new_path = env::join_paths(paths.iter()).unwrap(); /// env::set_var("PATH", &new_path); /// } @@ -355,7 +357,7 @@ impl Error for JoinPathsError { /// None => println!("Impossible to get your home dir!") /// } /// ``` -pub fn home_dir() -> Option { +pub fn home_dir() -> Option { os_imp::home_dir() } @@ -369,7 +371,7 @@ pub fn home_dir() -> Option { /// On Windows, returns the value of, in order, the 'TMP', 'TEMP', /// 'USERPROFILE' environment variable if any are set and not the empty /// string. Otherwise, tmpdir returns the path to the Windows directory. -pub fn temp_dir() -> Path { +pub fn temp_dir() -> PathBuf { os_imp::temp_dir() } @@ -396,7 +398,7 @@ pub fn temp_dir() -> Path { /// Err(e) => println!("failed to get current exe path: {}", e), /// }; /// ``` -pub fn current_exe() -> IoResult { +pub fn current_exe() -> io::Result { os_imp::current_exe() } @@ -825,6 +827,7 @@ mod tests { use iter::repeat; use rand::{self, Rng}; use ffi::{OsString, OsStr}; + use path::PathBuf; fn make_rand_name() -> OsString { let mut rng = rand::thread_rng(); @@ -944,7 +947,7 @@ mod tests { fn split_paths_unix() { fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { split_paths(unparsed).collect::>() == - parsed.iter().map(|s| Path::new(*s)).collect::>() + parsed.iter().map(|s| PathBuf::new(*s)).collect::>() } assert!(check_parse("", &mut [""])); diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs deleted file mode 100644 index 98c1b50a9bf..00000000000 --- a/src/libstd/fs.rs +++ /dev/null @@ -1,1503 +0,0 @@ -// 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. - -//! Filesystem manipulation operations -//! -//! This module contains basic methods to manipulate the contents of the local -//! filesystem. All methods in this module represent cross-platform filesystem -//! operations. Extra platform-specific functionality can be found in the -//! extension traits of `std::os::$platform`. - -#![unstable(feature = "fs")] - -use core::prelude::*; - -use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write}; -use path::{AsPath, Path, PathBuf}; -use sys::fs2 as fs_imp; -use sys_common::{AsInnerMut, FromInner, AsInner}; -use vec::Vec; - -/// A reference to an open file on the filesystem. -/// -/// An instance of a `File` can be read and/or written depending on what options -/// it was opened with. Files also implement `Seek` to alter the logical cursor -/// that the file contains internally. -/// -/// # Example -/// -/// ```no_run -/// use std::io::prelude::*; -/// use std::fs::File; -/// -/// # fn foo() -> std::io::Result<()> { -/// let mut f = try!(File::create("foo.txt")); -/// try!(f.write_all(b"Hello, world!")); -/// -/// let mut f = try!(File::open("foo.txt")); -/// let mut s = String::new(); -/// try!(f.read_to_string(&mut s)); -/// assert_eq!(s, "Hello, world!"); -/// # Ok(()) -/// # } -/// ``` -pub struct File { - inner: fs_imp::File, - path: PathBuf, -} - -/// Metadata information about a file. -/// -/// This structure is returned from the `metadata` function or method and -/// represents known metadata about a file such as its permissions, size, -/// modification times, etc. -pub struct Metadata(fs_imp::FileAttr); - -/// Iterator over the entries in a directory. -/// -/// This iterator is returned from the `read_dir` function of this module and -/// will yield instances of `io::Result`. Through a `DirEntry` -/// information like the entry's path and possibly other metadata can be -/// learned. -pub struct ReadDir(fs_imp::ReadDir); - -/// Entries returned by the `ReadDir` iterator. -/// -/// An instance of `DirEntry` represents an entry inside of a directory on the -/// filesystem. Each entry can be inspected via methods to learn about the full -/// path or possibly other metadata through per-platform extension traits. -pub struct DirEntry(fs_imp::DirEntry); - -/// An iterator that recursively walks over the contents of a directory. -pub struct WalkDir { - cur: Option, - stack: Vec>, -} - -/// Options and flags which can be used to configure how a file is opened. -/// -/// This builder exposes the ability to configure how a `File` is opened and -/// what operations are permitted on the open file. The `File::open` and -/// `File::create` methods are aliases for commonly used options using this -/// builder. -#[derive(Clone)] -pub struct OpenOptions(fs_imp::OpenOptions); - -/// Representation of the various permissions on a file. -/// -/// This module only currently provides one bit of information, `readonly`, -/// which is exposed on all currently supported platforms. Unix-specific -/// functionality, such as mode bits, is available through the -/// `os::unix::PermissionsExt` trait. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Permissions(fs_imp::FilePermissions); - -impl File { - /// Attempts to open a file in read-only mode. - /// - /// See the `OpenOptions::open` method for more details. - /// - /// # Errors - /// - /// This function will return an error if `path` does not already exist. - /// Other errors may also be returned according to `OpenOptions::open`. - pub fn open(path: &P) -> io::Result { - OpenOptions::new().read(true).open(path) - } - - /// Open a file in write-only mode. - /// - /// This function will create a file if it does not exist, - /// and will truncate it if it does. - /// - /// See the `OpenOptions::open` function for more details. - pub fn create(path: &P) -> io::Result { - OpenOptions::new().write(true).create(true).truncate(true).open(path) - } - - /// Returns the original path that was used to open this file. - pub fn path(&self) -> Option<&Path> { - Some(&self.path) - } - - /// Attempt to sync all OS-internal metadata to disk. - /// - /// This function will attempt to ensure that all in-core data reaches the - /// filesystem before returning. - pub fn sync_all(&self) -> io::Result<()> { - self.inner.fsync() - } - - /// This function is similar to `sync_all`, except that it may not - /// synchronize file metadata to the filesystem. - /// - /// This is intended for use cases that must synchronize content, but don't - /// need the metadata on disk. The goal of this method is to reduce disk - /// operations. - /// - /// Note that some platforms may simply implement this in terms of - /// `sync_all`. - pub fn sync_data(&self) -> io::Result<()> { - self.inner.datasync() - } - - /// Truncates or extends the underlying file, updating the size of - /// this file to become `size`. - /// - /// If the `size` is less than the current file's size, then the file will - /// be shrunk. If it is greater than the current file's size, then the file - /// will be extended to `size` and have all of the intermediate data filled - /// in with 0s. - pub fn set_len(&self, size: u64) -> io::Result<()> { - self.inner.truncate(size) - } - - /// Queries information about the underlying file. - pub fn metadata(&self) -> io::Result { - self.inner.file_attr().map(Metadata) - } -} - -impl AsInner for File { - fn as_inner(&self) -> &fs_imp::File { &self.inner } -} -impl Read for File { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.inner.read(buf) - } -} -impl Write for File { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.inner.write(buf) - } - fn flush(&mut self) -> io::Result<()> { self.inner.flush() } -} -impl Seek for File { - fn seek(&mut self, pos: SeekFrom) -> io::Result { - self.inner.seek(pos) - } -} -impl<'a> Read for &'a File { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.inner.read(buf) - } -} -impl<'a> Write for &'a File { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.inner.write(buf) - } - fn flush(&mut self) -> io::Result<()> { self.inner.flush() } -} -impl<'a> Seek for &'a File { - fn seek(&mut self, pos: SeekFrom) -> io::Result { - self.inner.seek(pos) - } -} - -impl OpenOptions { - /// Creates a blank net set of options ready for configuration. - /// - /// All options are initially set to `false`. - pub fn new() -> OpenOptions { - OpenOptions(fs_imp::OpenOptions::new()) - } - - /// Set the option for read access. - /// - /// This option, when true, will indicate that the file should be - /// `read`-able if opened. - pub fn read(&mut self, read: bool) -> &mut OpenOptions { - self.0.read(read); self - } - - /// Set the option for write access. - /// - /// This option, when true, will indicate that the file should be - /// `write`-able if opened. - pub fn write(&mut self, write: bool) -> &mut OpenOptions { - self.0.write(write); self - } - - /// Set the option for the append mode. - /// - /// This option, when true, means that writes will append to a file instead - /// of overwriting previous contents. - pub fn append(&mut self, append: bool) -> &mut OpenOptions { - self.0.append(append); self - } - - /// Set the option for truncating a previous file. - /// - /// If a file is successfully opened with this option set it will truncate - /// the file to 0 length if it already exists. - pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions { - self.0.truncate(truncate); self - } - - /// Set the option for creating a new file. - /// - /// This option indicates whether a new file will be created if the file - /// does not yet already exist. - pub fn create(&mut self, create: bool) -> &mut OpenOptions { - self.0.create(create); self - } - - /// Open a file at `path` with the options specified by `self`. - /// - /// # Errors - /// - /// This function will return an error under a number of different - /// circumstances, to include but not limited to: - /// - /// * Opening a file that does not exist with read access. - /// * Attempting to open a file with access that the user lacks - /// permissions for - /// * Filesystem-level errors (full disk, etc) - pub fn open(&self, path: &P) -> io::Result { - let path = path.as_path(); - let inner = try!(fs_imp::File::open(path, &self.0)); - - // On *BSD systems, we can open a directory as a file and read from - // it: fd=open("/tmp", O_RDONLY); read(fd, buf, N); due to an old - // tradition before the introduction of opendir(3). We explicitly - // reject it because there are few use cases. - if cfg!(not(any(target_os = "linux", target_os = "android"))) && - try!(inner.file_attr()).is_dir() { - Err(Error::new(ErrorKind::InvalidInput, "is a directory", None)) - } else { - Ok(File { path: path.to_path_buf(), inner: inner }) - } - } -} -impl AsInnerMut for OpenOptions { - fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 } -} - -impl Metadata { - /// Returns whether this metadata is for a directory. - pub fn is_dir(&self) -> bool { self.0.is_dir() } - - /// Returns whether this metadata is for a regular file. - pub fn is_file(&self) -> bool { self.0.is_file() } - - /// Returns the size of the file, in bytes, this metadata is for. - pub fn len(&self) -> u64 { self.0.size() } - - /// Returns the permissions of the file this metadata is for. - pub fn permissions(&self) -> Permissions { - Permissions(self.0.perm()) - } - - /// Returns the most recent access time for a file. - /// - /// The return value is in milliseconds since the epoch. - pub fn accessed(&self) -> u64 { self.0.accessed() } - - /// Returns the most recent modification time for a file. - /// - /// The return value is in milliseconds since the epoch. - pub fn modified(&self) -> u64 { self.0.modified() } -} - -impl Permissions { - /// Returns whether these permissions describe a readonly file. - pub fn readonly(&self) -> bool { self.0.readonly() } - - /// Modify the readonly flag for this set of permissions. - /// - /// This operation does **not** modify the filesystem. To modify the - /// filesystem use the `fs::set_permissions` function. - pub fn set_readonly(&mut self, readonly: bool) { - self.0.set_readonly(readonly) - } -} - -impl FromInner for Permissions { - fn from_inner(f: fs_imp::FilePermissions) -> Permissions { - Permissions(f) - } -} - -impl Iterator for ReadDir { - type Item = io::Result; - - fn next(&mut self) -> Option> { - self.0.next().map(|entry| entry.map(DirEntry)) - } -} - -impl DirEntry { - /// Returns the full path to the file that this entry represents. - /// - /// The full path is created by joining the original path to `read_dir` or - /// `walk_dir` with the filename of this entry. - pub fn path(&self) -> PathBuf { self.0.path() } -} - -/// Remove a file from the underlying filesystem. -/// -/// # Example -/// -/// ```rust,no_run -/// use std::fs; -/// -/// fs::remove_file("/some/file/path.txt"); -/// ``` -/// -/// Note that, just because an unlink call was successful, it is not -/// guaranteed that a file is immediately deleted (e.g. depending on -/// platform, other open file descriptors may prevent immediate removal). -/// -/// # Errors -/// -/// This function will return an error if `path` points to a directory, if the -/// user lacks permissions to remove the file, or if some other filesystem-level -/// error occurs. -pub fn remove_file(path: &P) -> io::Result<()> { - let path = path.as_path(); - let e = match fs_imp::unlink(path) { - Ok(()) => return Ok(()), - Err(e) => e, - }; - if !cfg!(windows) { return Err(e) } - - // On unix, a readonly file can be successfully removed. On windows, - // however, it cannot. To keep the two platforms in line with - // respect to their behavior, catch this case on windows, attempt to - // change it to read-write, and then remove the file. - if e.kind() != ErrorKind::PermissionDenied { return Err(e) } - - let attr = match metadata(path) { Ok(a) => a, Err(..) => return Err(e) }; - let mut perms = attr.permissions(); - if !perms.readonly() { return Err(e) } - perms.set_readonly(false); - - if set_permissions(path, perms).is_err() { return Err(e) } - if fs_imp::unlink(path).is_ok() { return Ok(()) } - - // Oops, try to put things back the way we found it - let _ = set_permissions(path, attr.permissions()); - Err(e) -} - -/// Given a path, query the file system to get information about a file, -/// directory, etc. -/// -/// This function will traverse soft links to query information about the -/// destination file. -/// -/// # Example -/// -/// ```rust,no_run -/// # fn foo() -> std::io::Result<()> { -/// use std::fs; -/// -/// let attr = try!(fs::metadata("/some/file/path.txt")); -/// // inspect attr ... -/// # Ok(()) -/// # } -/// ``` -/// -/// # Errors -/// -/// This function will return an error if the user lacks the requisite -/// permissions to perform a `metadata` call on the given `path` or if there -/// is no entry in the filesystem at the provided path. -pub fn metadata(path: &P) -> io::Result { - fs_imp::stat(path.as_path()).map(Metadata) -} - -/// Rename a file or directory to a new name. -/// -/// # Example -/// -/// ```rust,no_run -/// use std::fs; -/// -/// fs::rename("foo", "bar"); -/// ``` -/// -/// # Errors -/// -/// This function will return an error if the provided `from` doesn't exist, if -/// the process lacks permissions to view the contents, if `from` and `to` -/// reside on separate filesystems, or if some other intermittent I/O error -/// occurs. -pub fn rename(from: &P, to: &Q) - -> io::Result<()> { - fs_imp::rename(from.as_path(), to.as_path()) -} - -/// Copies the contents of one file to another. This function will also -/// copy the permission bits of the original file to the destination file. -/// -/// This function will **overwrite** the contents of `to`. -/// -/// Note that if `from` and `to` both point to the same file, then the file -/// will likely get truncated by this operation. -/// -/// # Example -/// -/// ```rust -/// use std::fs; -/// -/// fs::copy("foo.txt", "bar.txt"); -/// ``` -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not -/// limited to just these cases: -/// -/// * The `from` path is not a file -/// * The `from` file does not exist -/// * The current process does not have the permission rights to access -/// `from` or write `to` -pub fn copy(from: &P, to: &Q) - -> io::Result { - let from = from.as_path(); - if !from.is_file() { - return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation, - "the source path is not an existing file", - None)) - } - - let mut reader = try!(File::open(from)); - let mut writer = try!(File::create(to)); - let perm = try!(reader.metadata()).permissions(); - - let ret = try!(io::copy(&mut reader, &mut writer)); - try!(set_permissions(to, perm)); - Ok(ret) -} - -/// Creates a new hard link on the filesystem. -/// -/// The `dst` path will be a link pointing to the `src` path. Note that systems -/// often require these two paths to both be located on the same filesystem. -pub fn hard_link(src: &P, dst: &Q) - -> io::Result<()> { - fs_imp::link(src.as_path(), dst.as_path()) -} - -/// Creates a new soft link on the filesystem. -/// -/// The `dst` path will be a soft link pointing to the `src` path. -pub fn soft_link(src: &P, dst: &Q) - -> io::Result<()> { - fs_imp::symlink(src.as_path(), dst.as_path()) -} - -/// Reads a soft link, returning the file that the link points to. -/// -/// # Errors -/// -/// This function will return an error on failure. Failure conditions include -/// reading a file that does not exist or reading a file that is not a soft -/// link. -pub fn read_link(path: &P) -> io::Result { - fs_imp::readlink(path.as_path()) -} - -/// Create a new, empty directory at the provided path -/// -/// # Example -/// -/// ```rust -/// use std::fs; -/// -/// fs::create_dir("/some/dir"); -/// ``` -/// -/// # Errors -/// -/// This function will return an error if the user lacks permissions to make a -/// new directory at the provided `path`, or if the directory already exists. -pub fn create_dir(path: &P) -> io::Result<()> { - fs_imp::mkdir(path.as_path()) -} - -/// Recursively create a directory and all of its parent components if they -/// are missing. -/// -/// # Errors -/// -/// This function will fail if any directory in the path specified by `path` -/// does not already exist and it could not be created otherwise. The specific -/// error conditions for when a directory is being created (after it is -/// determined to not exist) are outlined by `fs::create_dir`. -pub fn create_dir_all(path: &P) -> io::Result<()> { - let path = path.as_path(); - if path.is_dir() { return Ok(()) } - match path.parent() { - Some(p) if p != path => try!(create_dir_all(p)), - _ => {} - } - create_dir(path) -} - -/// Remove an existing, empty directory -/// -/// # Example -/// -/// ```rust -/// use std::fs; -/// -/// fs::remove_dir("/some/dir"); -/// ``` -/// -/// # Errors -/// -/// This function will return an error if the user lacks permissions to remove -/// the directory at the provided `path`, or if the directory isn't empty. -pub fn remove_dir(path: &P) -> io::Result<()> { - fs_imp::rmdir(path.as_path()) -} - -/// Removes a directory at this path, after removing all its contents. Use -/// carefully! -/// -/// This function does **not** follow soft links and it will simply remove the -/// soft link itself. -/// -/// # Errors -/// -/// See `file::remove_file` and `fs::remove_dir` -pub fn remove_dir_all(path: &P) -> io::Result<()> { - let path = path.as_path(); - for child in try!(read_dir(path)) { - let child = try!(child).path(); - let stat = try!(lstat(&*child)); - if stat.is_dir() { - try!(remove_dir_all(&*child)); - } else { - try!(remove_file(&*child)); - } - } - return remove_dir(path); - - #[cfg(unix)] - fn lstat(path: &Path) -> io::Result { fs_imp::lstat(path) } - #[cfg(windows)] - fn lstat(path: &Path) -> io::Result { fs_imp::stat(path) } -} - -/// Returns an iterator over the entries within a directory. -/// -/// The iterator will yield instances of `io::Result`. New errors may -/// be encountered after an iterator is initially constructed. -/// -/// # Example -/// -/// ```rust -/// use std::io; -/// use std::fs::{self, PathExt, DirEntry}; -/// use std::path::Path; -/// -/// // one possible implementation of fs::walk_dir only visiting files -/// fn visit_dirs(dir: &Path, cb: &mut FnMut(DirEntry)) -> io::Result<()> { -/// if dir.is_dir() { -/// for entry in try!(fs::read_dir(dir)) { -/// let entry = try!(entry); -/// if entry.path().is_dir() { -/// try!(visit_dirs(&entry.path(), cb)); -/// } else { -/// cb(entry); -/// } -/// } -/// } -/// Ok(()) -/// } -/// ``` -/// -/// # Errors -/// -/// This function will return an error if the provided `path` doesn't exist, if -/// the process lacks permissions to view the contents or if the `path` points -/// at a non-directory file -pub fn read_dir(path: &P) -> io::Result { - fs_imp::readdir(path.as_path()).map(ReadDir) -} - -/// Returns an iterator that will recursively walk the directory structure -/// rooted at `path`. -/// -/// The path given will not be iterated over, and this will perform iteration in -/// some top-down order. The contents of unreadable subdirectories are ignored. -/// -/// The iterator will yield instances of `io::Result`. New errors may -/// be encountered after an iterator is initially constructed. -pub fn walk_dir(path: &P) -> io::Result { - let start = try!(read_dir(path)); - Ok(WalkDir { cur: Some(start), stack: Vec::new() }) -} - -impl Iterator for WalkDir { - type Item = io::Result; - - fn next(&mut self) -> Option> { - loop { - if let Some(ref mut cur) = self.cur { - match cur.next() { - Some(Err(e)) => return Some(Err(e)), - Some(Ok(next)) => { - let path = next.path(); - if path.is_dir() { - self.stack.push(read_dir(&*path)); - } - return Some(Ok(next)) - } - None => {} - } - } - self.cur = None; - match self.stack.pop() { - Some(Err(e)) => return Some(Err(e)), - Some(Ok(next)) => self.cur = Some(next), - None => return None, - } - } - } -} - -/// Utility methods for paths. -pub trait PathExt { - /// Get information on the file, directory, etc at this path. - /// - /// Consult the `fs::stat` documentation for more info. - /// - /// This call preserves identical runtime/error semantics with `file::stat`. - fn metadata(&self) -> io::Result; - - /// Boolean value indicator whether the underlying file exists on the local - /// filesystem. Returns false in exactly the cases where `fs::stat` fails. - fn exists(&self) -> bool; - - /// Whether the underlying implementation (be it a file path, or something - /// else) points at a "regular file" on the FS. Will return false for paths - /// to non-existent locations or directories or other non-regular files - /// (named pipes, etc). Follows links when making this determination. - fn is_file(&self) -> bool; - - /// Whether the underlying implementation (be it a file path, or something - /// else) is pointing at a directory in the underlying FS. Will return - /// false for paths to non-existent locations or if the item is not a - /// directory (eg files, named pipes, etc). Follows links when making this - /// determination. - fn is_dir(&self) -> bool; -} - -impl PathExt for Path { - fn metadata(&self) -> io::Result { metadata(self) } - - fn exists(&self) -> bool { metadata(self).is_ok() } - - fn is_file(&self) -> bool { - metadata(self).map(|s| s.is_file()).unwrap_or(false) - } - fn is_dir(&self) -> bool { - metadata(self).map(|s| s.is_dir()).unwrap_or(false) - } -} - -/// Changes the timestamps for a file's last modification and access time. -/// -/// The file at the path specified will have its last access time set to -/// `atime` and its modification time set to `mtime`. The times specified should -/// be in milliseconds. -pub fn set_file_times(path: &P, accessed: u64, - modified: u64) -> io::Result<()> { - fs_imp::utimes(path.as_path(), accessed, modified) -} - -/// Changes the permissions found on a file or a directory. -/// -/// # Example -/// -/// ``` -/// # fn foo() -> std::io::Result<()> { -/// use std::fs; -/// -/// let mut perms = try!(fs::metadata("foo.txt")).permissions(); -/// perms.set_readonly(true); -/// try!(fs::set_permissions("foo.txt", perms)); -/// # Ok(()) -/// # } -/// ``` -/// -/// # Errors -/// -/// This function will return an error if the provided `path` doesn't exist, if -/// the process lacks permissions to change the attributes of the file, or if -/// some other I/O error is encountered. -pub fn set_permissions(path: &P, perm: Permissions) - -> io::Result<()> { - fs_imp::set_perm(path.as_path(), perm.0) -} - -#[cfg(test)] -mod tests { - #![allow(deprecated)] //rand - - use prelude::v1::*; - use io::prelude::*; - - use fs::{self, File, OpenOptions}; - use io::{ErrorKind, SeekFrom}; - use path::PathBuf; - use path::Path as Path2; - use os; - use rand::{self, StdRng, Rng}; - use str; - - macro_rules! check { ($e:expr) => ( - match $e { - Ok(t) => t, - Err(e) => panic!("{} failed with: {}", stringify!($e), e), - } - ) } - - macro_rules! error { ($e:expr, $s:expr) => ( - match $e { - Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), - Err(ref err) => assert!(err.to_string().contains($s.as_slice()), - format!("`{}` did not contain `{}`", err, $s)) - } - ) } - - pub struct TempDir(PathBuf); - - impl TempDir { - fn join(&self, path: &str) -> PathBuf { - let TempDir(ref p) = *self; - p.join(path) - } - - fn path<'a>(&'a self) -> &'a Path2 { - let TempDir(ref p) = *self; - p - } - } - - impl Drop for TempDir { - fn drop(&mut self) { - // Gee, seeing how we're testing the fs module I sure hope that we - // at least implement this correctly! - let TempDir(ref p) = *self; - check!(fs::remove_dir_all(p)); - } - } - - pub fn tmpdir() -> TempDir { - let s = os::tmpdir(); - let p = Path2::new(s.as_str().unwrap()); - let ret = p.join(&format!("rust-{}", rand::random::())); - check!(fs::create_dir(&ret)); - TempDir(ret) - } - - #[test] - fn file_test_io_smoke_test() { - let message = "it's alright. have a good time"; - let tmpdir = tmpdir(); - let filename = &tmpdir.join("file_rt_io_file_test.txt"); - { - let mut write_stream = check!(File::create(filename)); - check!(write_stream.write(message.as_bytes())); - } - { - let mut read_stream = check!(File::open(filename)); - let mut read_buf = [0; 1028]; - let read_str = match check!(read_stream.read(&mut read_buf)) { - -1|0 => panic!("shouldn't happen"), - n => str::from_utf8(&read_buf[..n]).unwrap().to_string() - }; - assert_eq!(read_str.as_slice(), message); - } - check!(fs::remove_file(filename)); - } - - #[test] - fn invalid_path_raises() { - let tmpdir = tmpdir(); - let filename = &tmpdir.join("file_that_does_not_exist.txt"); - let result = File::open(filename); - - if cfg!(unix) { - error!(result, "o such file or directory"); - } - // error!(result, "couldn't open path as file"); - // error!(result, format!("path={}; mode=open; access=read", filename.display())); - } - - #[test] - fn file_test_iounlinking_invalid_path_should_raise_condition() { - let tmpdir = tmpdir(); - let filename = &tmpdir.join("file_another_file_that_does_not_exist.txt"); - - let result = fs::remove_file(filename); - - if cfg!(unix) { - error!(result, "o such file or directory"); - } - // error!(result, "couldn't unlink path"); - // error!(result, format!("path={}", filename.display())); - } - - #[test] - fn file_test_io_non_positional_read() { - let message: &str = "ten-four"; - let mut read_mem = [0; 8]; - let tmpdir = tmpdir(); - let filename = &tmpdir.join("file_rt_io_file_test_positional.txt"); - { - let mut rw_stream = check!(File::create(filename)); - check!(rw_stream.write(message.as_bytes())); - } - { - let mut read_stream = check!(File::open(filename)); - { - let read_buf = &mut read_mem[0..4]; - check!(read_stream.read(read_buf)); - } - { - let read_buf = &mut read_mem[4..8]; - check!(read_stream.read(read_buf)); - } - } - check!(fs::remove_file(filename)); - let read_str = str::from_utf8(&read_mem).unwrap(); - assert_eq!(read_str, message); - } - - #[test] - fn file_test_io_seek_and_tell_smoke_test() { - let message = "ten-four"; - let mut read_mem = [0; 4]; - let set_cursor = 4 as u64; - let mut tell_pos_pre_read; - let mut tell_pos_post_read; - let tmpdir = tmpdir(); - let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt"); - { - let mut rw_stream = check!(File::create(filename)); - check!(rw_stream.write(message.as_bytes())); - } - { - let mut read_stream = check!(File::open(filename)); - check!(read_stream.seek(SeekFrom::Start(set_cursor))); - tell_pos_pre_read = check!(read_stream.seek(SeekFrom::Current(0))); - check!(read_stream.read(&mut read_mem)); - tell_pos_post_read = check!(read_stream.seek(SeekFrom::Current(0))); - } - check!(fs::remove_file(filename)); - let read_str = str::from_utf8(&read_mem).unwrap(); - assert_eq!(read_str, &message[4..8]); - assert_eq!(tell_pos_pre_read, set_cursor); - assert_eq!(tell_pos_post_read, message.len() as u64); - } - - #[test] - fn file_test_io_seek_and_write() { - let initial_msg = "food-is-yummy"; - let overwrite_msg = "-the-bar!!"; - let final_msg = "foo-the-bar!!"; - let seek_idx = 3; - let mut read_mem = [0; 13]; - let tmpdir = tmpdir(); - let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt"); - { - let mut rw_stream = check!(File::create(filename)); - check!(rw_stream.write(initial_msg.as_bytes())); - check!(rw_stream.seek(SeekFrom::Start(seek_idx))); - check!(rw_stream.write(overwrite_msg.as_bytes())); - } - { - let mut read_stream = check!(File::open(filename)); - check!(read_stream.read(&mut read_mem)); - } - check!(fs::remove_file(filename)); - let read_str = str::from_utf8(&read_mem).unwrap(); - assert!(read_str == final_msg); - } - - #[test] - fn file_test_io_seek_shakedown() { - // 01234567890123 - let initial_msg = "qwer-asdf-zxcv"; - let chunk_one: &str = "qwer"; - let chunk_two: &str = "asdf"; - let chunk_three: &str = "zxcv"; - let mut read_mem = [0; 4]; - let tmpdir = tmpdir(); - let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt"); - { - let mut rw_stream = check!(File::create(filename)); - check!(rw_stream.write(initial_msg.as_bytes())); - } - { - let mut read_stream = check!(File::open(filename)); - - check!(read_stream.seek(SeekFrom::End(-4))); - check!(read_stream.read(&mut read_mem)); - assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_three); - - check!(read_stream.seek(SeekFrom::Current(-9))); - check!(read_stream.read(&mut read_mem)); - assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_two); - - check!(read_stream.seek(SeekFrom::Start(0))); - check!(read_stream.read(&mut read_mem)); - assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_one); - } - check!(fs::remove_file(filename)); - } - - #[test] - fn file_test_stat_is_correct_on_is_file() { - let tmpdir = tmpdir(); - let filename = &tmpdir.join("file_stat_correct_on_is_file.txt"); - { - let mut opts = OpenOptions::new(); - let mut fs = check!(opts.read(true).write(true) - .create(true).open(filename)); - let msg = "hw"; - fs.write(msg.as_bytes()).unwrap(); - - let fstat_res = check!(fs.metadata()); - assert!(fstat_res.is_file()); - } - let stat_res_fn = check!(fs::metadata(filename)); - assert!(stat_res_fn.is_file()); - let stat_res_meth = check!(filename.metadata()); - assert!(stat_res_meth.is_file()); - check!(fs::remove_file(filename)); - } - - #[test] - fn file_test_stat_is_correct_on_is_dir() { - let tmpdir = tmpdir(); - let filename = &tmpdir.join("file_stat_correct_on_is_dir"); - check!(fs::create_dir(filename)); - let stat_res_fn = check!(fs::metadata(filename)); - assert!(stat_res_fn.is_dir()); - let stat_res_meth = check!(filename.metadata()); - assert!(stat_res_meth.is_dir()); - check!(fs::remove_dir(filename)); - } - - #[test] - fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() { - let tmpdir = tmpdir(); - let dir = &tmpdir.join("fileinfo_false_on_dir"); - check!(fs::create_dir(dir)); - assert!(dir.is_file() == false); - check!(fs::remove_dir(dir)); - } - - #[test] - fn file_test_fileinfo_check_exists_before_and_after_file_creation() { - let tmpdir = tmpdir(); - let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt"); - check!(check!(File::create(file)).write(b"foo")); - assert!(file.exists()); - check!(fs::remove_file(file)); - assert!(!file.exists()); - } - - #[test] - fn file_test_directoryinfo_check_exists_before_and_after_mkdir() { - let tmpdir = tmpdir(); - let dir = &tmpdir.join("before_and_after_dir"); - assert!(!dir.exists()); - check!(fs::create_dir(dir)); - assert!(dir.exists()); - assert!(dir.is_dir()); - check!(fs::remove_dir(dir)); - assert!(!dir.exists()); - } - - #[test] - fn file_test_directoryinfo_readdir() { - let tmpdir = tmpdir(); - let dir = &tmpdir.join("di_readdir"); - check!(fs::create_dir(dir)); - let prefix = "foo"; - for n in range(0, 3) { - let f = dir.join(&format!("{}.txt", n)); - let mut w = check!(File::create(&f)); - let msg_str = format!("{}{}", prefix, n.to_string()); - let msg = msg_str.as_bytes(); - check!(w.write(msg)); - } - let files = check!(fs::read_dir(dir)); - let mut mem = [0u8; 4]; - for f in files { - let f = f.unwrap().path(); - { - let n = f.file_stem().unwrap(); - check!(check!(File::open(&f)).read(&mut mem)); - let read_str = str::from_utf8(&mem).unwrap(); - let expected = format!("{}{}", prefix, n.to_str().unwrap()); - assert_eq!(expected.as_slice(), read_str); - } - check!(fs::remove_file(&f)); - } - check!(fs::remove_dir(dir)); - } - - #[test] - fn file_test_walk_dir() { - let tmpdir = tmpdir(); - let dir = &tmpdir.join("walk_dir"); - check!(fs::create_dir(dir)); - - let dir1 = &dir.join("01/02/03"); - check!(fs::create_dir_all(dir1)); - check!(File::create(&dir1.join("04"))); - - let dir2 = &dir.join("11/12/13"); - check!(fs::create_dir_all(dir2)); - check!(File::create(&dir2.join("14"))); - - let files = check!(fs::walk_dir(dir)); - let mut cur = [0u8; 2]; - for f in files { - let f = f.unwrap().path(); - let stem = f.file_stem().unwrap().to_str().unwrap(); - let root = stem.as_bytes()[0] - b'0'; - let name = stem.as_bytes()[1] - b'0'; - assert!(cur[root as usize] < name); - cur[root as usize] = name; - } - - check!(fs::remove_dir_all(dir)); - } - - #[test] - fn mkdir_path_already_exists_error() { - let tmpdir = tmpdir(); - let dir = &tmpdir.join("mkdir_error_twice"); - check!(fs::create_dir(dir)); - let e = fs::create_dir(dir).err().unwrap(); - assert_eq!(e.kind(), ErrorKind::PathAlreadyExists); - } - - #[test] - fn recursive_mkdir() { - let tmpdir = tmpdir(); - let dir = tmpdir.join("d1/d2"); - check!(fs::create_dir_all(&dir)); - assert!(dir.is_dir()) - } - - #[test] - fn recursive_mkdir_failure() { - let tmpdir = tmpdir(); - let dir = tmpdir.join("d1"); - let file = dir.join("f1"); - - check!(fs::create_dir_all(&dir)); - check!(File::create(&file)); - - let result = fs::create_dir_all(&file); - - assert!(result.is_err()); - // error!(result, "couldn't recursively mkdir"); - // error!(result, "couldn't create directory"); - // error!(result, "mode=0700"); - // error!(result, format!("path={}", file.display())); - } - - #[test] - fn recursive_mkdir_slash() { - check!(fs::create_dir_all(&Path2::new("/"))); - } - - // FIXME(#12795) depends on lstat to work on windows - #[cfg(not(windows))] - #[test] - fn recursive_rmdir() { - let tmpdir = tmpdir(); - let d1 = tmpdir.join("d1"); - let dt = d1.join("t"); - let dtt = dt.join("t"); - let d2 = tmpdir.join("d2"); - let canary = d2.join("do_not_delete"); - check!(fs::create_dir_all(&dtt)); - check!(fs::create_dir_all(&d2)); - check!(check!(File::create(&canary)).write(b"foo")); - check!(fs::soft_link(&d2, &dt.join("d2"))); - check!(fs::remove_dir_all(&d1)); - - assert!(!d1.is_dir()); - assert!(canary.exists()); - } - - #[test] - fn unicode_path_is_dir() { - assert!(Path2::new(".").is_dir()); - assert!(!Path2::new("test/stdtest/fs.rs").is_dir()); - - let tmpdir = tmpdir(); - - let mut dirpath = tmpdir.path().to_path_buf(); - dirpath.push(&format!("test-가一ー你好")); - check!(fs::create_dir(&dirpath)); - assert!(dirpath.is_dir()); - - let mut filepath = dirpath; - filepath.push("unicode-file-\u{ac00}\u{4e00}\u{30fc}\u{4f60}\u{597d}.rs"); - check!(File::create(&filepath)); // ignore return; touch only - assert!(!filepath.is_dir()); - assert!(filepath.exists()); - } - - #[test] - fn unicode_path_exists() { - assert!(Path2::new(".").exists()); - assert!(!Path2::new("test/nonexistent-bogus-path").exists()); - - let tmpdir = tmpdir(); - let unicode = tmpdir.path(); - let unicode = unicode.join(&format!("test-각丁ー再见")); - check!(fs::create_dir(&unicode)); - assert!(unicode.exists()); - assert!(!Path2::new("test/unicode-bogus-path-각丁ー再见").exists()); - } - - #[test] - fn copy_file_does_not_exist() { - let from = Path2::new("test/nonexistent-bogus-path"); - let to = Path2::new("test/other-bogus-path"); - - match fs::copy(&from, &to) { - Ok(..) => panic!(), - Err(..) => { - assert!(!from.exists()); - assert!(!to.exists()); - } - } - } - - #[test] - fn copy_file_ok() { - let tmpdir = tmpdir(); - let input = tmpdir.join("in.txt"); - let out = tmpdir.join("out.txt"); - - check!(check!(File::create(&input)).write(b"hello")); - check!(fs::copy(&input, &out)); - let mut v = Vec::new(); - check!(check!(File::open(&out)).read_to_end(&mut v)); - assert_eq!(v.as_slice(), b"hello"); - - assert_eq!(check!(input.metadata()).permissions(), - check!(out.metadata()).permissions()); - } - - #[test] - fn copy_file_dst_dir() { - let tmpdir = tmpdir(); - let out = tmpdir.join("out"); - - check!(File::create(&out)); - match fs::copy(&*out, tmpdir.path()) { - Ok(..) => panic!(), Err(..) => {} - } - } - - #[test] - fn copy_file_dst_exists() { - let tmpdir = tmpdir(); - let input = tmpdir.join("in"); - let output = tmpdir.join("out"); - - check!(check!(File::create(&input)).write("foo".as_bytes())); - check!(check!(File::create(&output)).write("bar".as_bytes())); - check!(fs::copy(&input, &output)); - - let mut v = Vec::new(); - check!(check!(File::open(&output)).read_to_end(&mut v)); - assert_eq!(v, b"foo".to_vec()); - } - - #[test] - fn copy_file_src_dir() { - let tmpdir = tmpdir(); - let out = tmpdir.join("out"); - - match fs::copy(tmpdir.path(), &out) { - Ok(..) => panic!(), Err(..) => {} - } - assert!(!out.exists()); - } - - #[test] - fn copy_file_preserves_perm_bits() { - let tmpdir = tmpdir(); - let input = tmpdir.join("in.txt"); - let out = tmpdir.join("out.txt"); - - let attr = check!(check!(File::create(&input)).metadata()); - let mut p = attr.permissions(); - p.set_readonly(true); - check!(fs::set_permissions(&input, p)); - check!(fs::copy(&input, &out)); - assert!(check!(out.metadata()).permissions().readonly()); - } - - #[cfg(not(windows))] // FIXME(#10264) operation not permitted? - #[test] - fn symlinks_work() { - let tmpdir = tmpdir(); - let input = tmpdir.join("in.txt"); - let out = tmpdir.join("out.txt"); - - check!(check!(File::create(&input)).write("foobar".as_bytes())); - check!(fs::soft_link(&input, &out)); - // if cfg!(not(windows)) { - // assert_eq!(check!(lstat(&out)).kind, FileType::Symlink); - // assert_eq!(check!(out.lstat()).kind, FileType::Symlink); - // } - assert_eq!(check!(fs::metadata(&out)).len(), - check!(fs::metadata(&input)).len()); - let mut v = Vec::new(); - check!(check!(File::open(&out)).read_to_end(&mut v)); - assert_eq!(v, b"foobar".to_vec()); - } - - #[cfg(not(windows))] // apparently windows doesn't like symlinks - #[test] - fn symlink_noexist() { - let tmpdir = tmpdir(); - // symlinks can point to things that don't exist - check!(fs::soft_link(&tmpdir.join("foo"), &tmpdir.join("bar"))); - assert_eq!(check!(fs::read_link(&tmpdir.join("bar"))), - tmpdir.join("foo")); - } - - #[test] - fn readlink_not_symlink() { - let tmpdir = tmpdir(); - match fs::read_link(tmpdir.path()) { - Ok(..) => panic!("wanted a failure"), - Err(..) => {} - } - } - - #[test] - fn links_work() { - let tmpdir = tmpdir(); - let input = tmpdir.join("in.txt"); - let out = tmpdir.join("out.txt"); - - check!(check!(File::create(&input)).write("foobar".as_bytes())); - check!(fs::hard_link(&input, &out)); - assert_eq!(check!(fs::metadata(&out)).len(), - check!(fs::metadata(&input)).len()); - assert_eq!(check!(fs::metadata(&out)).len(), - check!(input.metadata()).len()); - let mut v = Vec::new(); - check!(check!(File::open(&out)).read_to_end(&mut v)); - assert_eq!(v, b"foobar".to_vec()); - - // can't link to yourself - match fs::hard_link(&input, &input) { - Ok(..) => panic!("wanted a failure"), - Err(..) => {} - } - // can't link to something that doesn't exist - match fs::hard_link(&tmpdir.join("foo"), &tmpdir.join("bar")) { - Ok(..) => panic!("wanted a failure"), - Err(..) => {} - } - } - - #[test] - fn chmod_works() { - let tmpdir = tmpdir(); - let file = tmpdir.join("in.txt"); - - check!(File::create(&file)); - let attr = check!(fs::metadata(&file)); - assert!(!attr.permissions().readonly()); - let mut p = attr.permissions(); - p.set_readonly(true); - check!(fs::set_permissions(&file, p.clone())); - let attr = check!(fs::metadata(&file)); - assert!(attr.permissions().readonly()); - - match fs::set_permissions(&tmpdir.join("foo"), p) { - Ok(..) => panic!("wanted a panic"), - Err(..) => {} - } - } - - #[test] - fn sync_doesnt_kill_anything() { - let tmpdir = tmpdir(); - let path = tmpdir.join("in.txt"); - - let mut file = check!(File::create(&path)); - check!(file.sync_all()); - check!(file.sync_data()); - check!(file.write(b"foo")); - check!(file.sync_all()); - check!(file.sync_data()); - } - - #[test] - fn truncate_works() { - let tmpdir = tmpdir(); - let path = tmpdir.join("in.txt"); - - let mut file = check!(File::create(&path)); - check!(file.write(b"foo")); - check!(file.sync_all()); - - // Do some simple things with truncation - assert_eq!(check!(file.metadata()).len(), 3); - check!(file.set_len(10)); - assert_eq!(check!(file.metadata()).len(), 10); - check!(file.write(b"bar")); - check!(file.sync_all()); - assert_eq!(check!(file.metadata()).len(), 10); - - let mut v = Vec::new(); - check!(check!(File::open(&path)).read_to_end(&mut v)); - assert_eq!(v, b"foobar\0\0\0\0".to_vec()); - - // Truncate to a smaller length, don't seek, and then write something. - // Ensure that the intermediate zeroes are all filled in (we're seeked - // past the end of the file). - check!(file.set_len(2)); - assert_eq!(check!(file.metadata()).len(), 2); - check!(file.write(b"wut")); - check!(file.sync_all()); - assert_eq!(check!(file.metadata()).len(), 9); - let mut v = Vec::new(); - check!(check!(File::open(&path)).read_to_end(&mut v)); - assert_eq!(v, b"fo\0\0\0\0wut".to_vec()); - } - - #[test] - fn open_flavors() { - use fs::OpenOptions as OO; - fn c(t: &T) -> T { t.clone() } - - let tmpdir = tmpdir(); - - let mut r = OO::new(); r.read(true); - let mut w = OO::new(); w.write(true); - let mut rw = OO::new(); rw.write(true).read(true); - - match r.open(&tmpdir.join("a")) { - Ok(..) => panic!(), Err(..) => {} - } - - // Perform each one twice to make sure that it succeeds the second time - // (where the file exists) - check!(c(&w).create(true).open(&tmpdir.join("b"))); - assert!(tmpdir.join("b").exists()); - check!(c(&w).create(true).open(&tmpdir.join("b"))); - check!(w.open(&tmpdir.join("b"))); - - check!(c(&rw).create(true).open(&tmpdir.join("c"))); - assert!(tmpdir.join("c").exists()); - check!(c(&rw).create(true).open(&tmpdir.join("c"))); - check!(rw.open(&tmpdir.join("c"))); - - check!(c(&w).append(true).create(true).open(&tmpdir.join("d"))); - assert!(tmpdir.join("d").exists()); - check!(c(&w).append(true).create(true).open(&tmpdir.join("d"))); - check!(c(&w).append(true).open(&tmpdir.join("d"))); - - check!(c(&rw).append(true).create(true).open(&tmpdir.join("e"))); - assert!(tmpdir.join("e").exists()); - check!(c(&rw).append(true).create(true).open(&tmpdir.join("e"))); - check!(c(&rw).append(true).open(&tmpdir.join("e"))); - - check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f"))); - assert!(tmpdir.join("f").exists()); - check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f"))); - check!(c(&w).truncate(true).open(&tmpdir.join("f"))); - - check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g"))); - assert!(tmpdir.join("g").exists()); - check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g"))); - check!(c(&rw).truncate(true).open(&tmpdir.join("g"))); - - check!(check!(File::create(&tmpdir.join("h"))).write("foo".as_bytes())); - check!(r.open(&tmpdir.join("h"))); - { - let mut f = check!(r.open(&tmpdir.join("h"))); - assert!(f.write("wut".as_bytes()).is_err()); - } - assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3); - { - let mut f = check!(c(&w).append(true).open(&tmpdir.join("h"))); - check!(f.write("bar".as_bytes())); - } - assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 6); - { - let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h"))); - check!(f.write("bar".as_bytes())); - } - assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3); - } - - #[test] - fn utime() { - let tmpdir = tmpdir(); - let path = tmpdir.join("a"); - check!(File::create(&path)); - // These numbers have to be bigger than the time in the day to account - // for timezones Windows in particular will fail in certain timezones - // with small enough values - check!(fs::set_file_times(&path, 100000, 200000)); - assert_eq!(check!(path.metadata()).accessed(), 100000); - assert_eq!(check!(path.metadata()).modified(), 200000); - } - - #[test] - fn utime_noexist() { - let tmpdir = tmpdir(); - - match fs::set_file_times(&tmpdir.join("a"), 100, 200) { - Ok(..) => panic!(), - Err(..) => {} - } - } - - #[test] - fn binary_file() { - let mut bytes = [0; 1024]; - StdRng::new().ok().unwrap().fill_bytes(&mut bytes); - - let tmpdir = tmpdir(); - - check!(check!(File::create(&tmpdir.join("test"))).write(&bytes)); - let mut v = Vec::new(); - check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v)); - assert!(v == bytes.as_slice()); - } - - #[test] - fn unlink_readonly() { - let tmpdir = tmpdir(); - let path = tmpdir.join("file"); - check!(File::create(&path)); - let mut perm = check!(fs::metadata(&path)).permissions(); - perm.set_readonly(true); - check!(fs::set_permissions(&path, perm)); - check!(fs::remove_file(&path)); - } -} diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs new file mode 100644 index 00000000000..aa211758621 --- /dev/null +++ b/src/libstd/fs/mod.rs @@ -0,0 +1,1507 @@ +// 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. + +//! Filesystem manipulation operations +//! +//! This module contains basic methods to manipulate the contents of the local +//! filesystem. All methods in this module represent cross-platform filesystem +//! operations. Extra platform-specific functionality can be found in the +//! extension traits of `std::os::$platform`. + +#![unstable(feature = "fs")] + +use core::prelude::*; + +use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write}; +use path::{AsPath, Path, PathBuf}; +use sys::fs2 as fs_imp; +use sys_common::{AsInnerMut, FromInner, AsInner}; +use vec::Vec; + +pub use self::tempdir::TempDir; + +mod tempdir; + +/// A reference to an open file on the filesystem. +/// +/// An instance of a `File` can be read and/or written depending on what options +/// it was opened with. Files also implement `Seek` to alter the logical cursor +/// that the file contains internally. +/// +/// # Example +/// +/// ```no_run +/// use std::io::prelude::*; +/// use std::fs::File; +/// +/// # fn foo() -> std::io::Result<()> { +/// let mut f = try!(File::create("foo.txt")); +/// try!(f.write_all(b"Hello, world!")); +/// +/// let mut f = try!(File::open("foo.txt")); +/// let mut s = String::new(); +/// try!(f.read_to_string(&mut s)); +/// assert_eq!(s, "Hello, world!"); +/// # Ok(()) +/// # } +/// ``` +pub struct File { + inner: fs_imp::File, + path: PathBuf, +} + +/// Metadata information about a file. +/// +/// This structure is returned from the `metadata` function or method and +/// represents known metadata about a file such as its permissions, size, +/// modification times, etc. +pub struct Metadata(fs_imp::FileAttr); + +/// Iterator over the entries in a directory. +/// +/// This iterator is returned from the `read_dir` function of this module and +/// will yield instances of `io::Result`. Through a `DirEntry` +/// information like the entry's path and possibly other metadata can be +/// learned. +pub struct ReadDir(fs_imp::ReadDir); + +/// Entries returned by the `ReadDir` iterator. +/// +/// An instance of `DirEntry` represents an entry inside of a directory on the +/// filesystem. Each entry can be inspected via methods to learn about the full +/// path or possibly other metadata through per-platform extension traits. +pub struct DirEntry(fs_imp::DirEntry); + +/// An iterator that recursively walks over the contents of a directory. +pub struct WalkDir { + cur: Option, + stack: Vec>, +} + +/// Options and flags which can be used to configure how a file is opened. +/// +/// This builder exposes the ability to configure how a `File` is opened and +/// what operations are permitted on the open file. The `File::open` and +/// `File::create` methods are aliases for commonly used options using this +/// builder. +#[derive(Clone)] +pub struct OpenOptions(fs_imp::OpenOptions); + +/// Representation of the various permissions on a file. +/// +/// This module only currently provides one bit of information, `readonly`, +/// which is exposed on all currently supported platforms. Unix-specific +/// functionality, such as mode bits, is available through the +/// `os::unix::PermissionsExt` trait. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Permissions(fs_imp::FilePermissions); + +impl File { + /// Attempts to open a file in read-only mode. + /// + /// See the `OpenOptions::open` method for more details. + /// + /// # Errors + /// + /// This function will return an error if `path` does not already exist. + /// Other errors may also be returned according to `OpenOptions::open`. + pub fn open(path: &P) -> io::Result { + OpenOptions::new().read(true).open(path) + } + + /// Open a file in write-only mode. + /// + /// This function will create a file if it does not exist, + /// and will truncate it if it does. + /// + /// See the `OpenOptions::open` function for more details. + pub fn create(path: &P) -> io::Result { + OpenOptions::new().write(true).create(true).truncate(true).open(path) + } + + /// Returns the original path that was used to open this file. + pub fn path(&self) -> Option<&Path> { + Some(&self.path) + } + + /// Attempt to sync all OS-internal metadata to disk. + /// + /// This function will attempt to ensure that all in-core data reaches the + /// filesystem before returning. + pub fn sync_all(&self) -> io::Result<()> { + self.inner.fsync() + } + + /// This function is similar to `sync_all`, except that it may not + /// synchronize file metadata to the filesystem. + /// + /// This is intended for use cases that must synchronize content, but don't + /// need the metadata on disk. The goal of this method is to reduce disk + /// operations. + /// + /// Note that some platforms may simply implement this in terms of + /// `sync_all`. + pub fn sync_data(&self) -> io::Result<()> { + self.inner.datasync() + } + + /// Truncates or extends the underlying file, updating the size of + /// this file to become `size`. + /// + /// If the `size` is less than the current file's size, then the file will + /// be shrunk. If it is greater than the current file's size, then the file + /// will be extended to `size` and have all of the intermediate data filled + /// in with 0s. + pub fn set_len(&self, size: u64) -> io::Result<()> { + self.inner.truncate(size) + } + + /// Queries information about the underlying file. + pub fn metadata(&self) -> io::Result { + self.inner.file_attr().map(Metadata) + } +} + +impl AsInner for File { + fn as_inner(&self) -> &fs_imp::File { &self.inner } +} +impl Read for File { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.inner.read(buf) + } +} +impl Write for File { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.inner.write(buf) + } + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } +} +impl Seek for File { + fn seek(&mut self, pos: SeekFrom) -> io::Result { + self.inner.seek(pos) + } +} +impl<'a> Read for &'a File { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.inner.read(buf) + } +} +impl<'a> Write for &'a File { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.inner.write(buf) + } + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } +} +impl<'a> Seek for &'a File { + fn seek(&mut self, pos: SeekFrom) -> io::Result { + self.inner.seek(pos) + } +} + +impl OpenOptions { + /// Creates a blank net set of options ready for configuration. + /// + /// All options are initially set to `false`. + pub fn new() -> OpenOptions { + OpenOptions(fs_imp::OpenOptions::new()) + } + + /// Set the option for read access. + /// + /// This option, when true, will indicate that the file should be + /// `read`-able if opened. + pub fn read(&mut self, read: bool) -> &mut OpenOptions { + self.0.read(read); self + } + + /// Set the option for write access. + /// + /// This option, when true, will indicate that the file should be + /// `write`-able if opened. + pub fn write(&mut self, write: bool) -> &mut OpenOptions { + self.0.write(write); self + } + + /// Set the option for the append mode. + /// + /// This option, when true, means that writes will append to a file instead + /// of overwriting previous contents. + pub fn append(&mut self, append: bool) -> &mut OpenOptions { + self.0.append(append); self + } + + /// Set the option for truncating a previous file. + /// + /// If a file is successfully opened with this option set it will truncate + /// the file to 0 length if it already exists. + pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions { + self.0.truncate(truncate); self + } + + /// Set the option for creating a new file. + /// + /// This option indicates whether a new file will be created if the file + /// does not yet already exist. + pub fn create(&mut self, create: bool) -> &mut OpenOptions { + self.0.create(create); self + } + + /// Open a file at `path` with the options specified by `self`. + /// + /// # Errors + /// + /// This function will return an error under a number of different + /// circumstances, to include but not limited to: + /// + /// * Opening a file that does not exist with read access. + /// * Attempting to open a file with access that the user lacks + /// permissions for + /// * Filesystem-level errors (full disk, etc) + pub fn open(&self, path: &P) -> io::Result { + let path = path.as_path(); + let inner = try!(fs_imp::File::open(path, &self.0)); + + // On *BSD systems, we can open a directory as a file and read from + // it: fd=open("/tmp", O_RDONLY); read(fd, buf, N); due to an old + // tradition before the introduction of opendir(3). We explicitly + // reject it because there are few use cases. + if cfg!(not(any(target_os = "linux", target_os = "android"))) && + try!(inner.file_attr()).is_dir() { + Err(Error::new(ErrorKind::InvalidInput, "is a directory", None)) + } else { + Ok(File { path: path.to_path_buf(), inner: inner }) + } + } +} +impl AsInnerMut for OpenOptions { + fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 } +} + +impl Metadata { + /// Returns whether this metadata is for a directory. + pub fn is_dir(&self) -> bool { self.0.is_dir() } + + /// Returns whether this metadata is for a regular file. + pub fn is_file(&self) -> bool { self.0.is_file() } + + /// Returns the size of the file, in bytes, this metadata is for. + pub fn len(&self) -> u64 { self.0.size() } + + /// Returns the permissions of the file this metadata is for. + pub fn permissions(&self) -> Permissions { + Permissions(self.0.perm()) + } + + /// Returns the most recent access time for a file. + /// + /// The return value is in milliseconds since the epoch. + pub fn accessed(&self) -> u64 { self.0.accessed() } + + /// Returns the most recent modification time for a file. + /// + /// The return value is in milliseconds since the epoch. + pub fn modified(&self) -> u64 { self.0.modified() } +} + +impl Permissions { + /// Returns whether these permissions describe a readonly file. + pub fn readonly(&self) -> bool { self.0.readonly() } + + /// Modify the readonly flag for this set of permissions. + /// + /// This operation does **not** modify the filesystem. To modify the + /// filesystem use the `fs::set_permissions` function. + pub fn set_readonly(&mut self, readonly: bool) { + self.0.set_readonly(readonly) + } +} + +impl FromInner for Permissions { + fn from_inner(f: fs_imp::FilePermissions) -> Permissions { + Permissions(f) + } +} + +impl Iterator for ReadDir { + type Item = io::Result; + + fn next(&mut self) -> Option> { + self.0.next().map(|entry| entry.map(DirEntry)) + } +} + +impl DirEntry { + /// Returns the full path to the file that this entry represents. + /// + /// The full path is created by joining the original path to `read_dir` or + /// `walk_dir` with the filename of this entry. + pub fn path(&self) -> PathBuf { self.0.path() } +} + +/// Remove a file from the underlying filesystem. +/// +/// # Example +/// +/// ```rust,no_run +/// use std::fs; +/// +/// fs::remove_file("/some/file/path.txt"); +/// ``` +/// +/// Note that, just because an unlink call was successful, it is not +/// guaranteed that a file is immediately deleted (e.g. depending on +/// platform, other open file descriptors may prevent immediate removal). +/// +/// # Errors +/// +/// This function will return an error if `path` points to a directory, if the +/// user lacks permissions to remove the file, or if some other filesystem-level +/// error occurs. +pub fn remove_file(path: &P) -> io::Result<()> { + let path = path.as_path(); + let e = match fs_imp::unlink(path) { + Ok(()) => return Ok(()), + Err(e) => e, + }; + if !cfg!(windows) { return Err(e) } + + // On unix, a readonly file can be successfully removed. On windows, + // however, it cannot. To keep the two platforms in line with + // respect to their behavior, catch this case on windows, attempt to + // change it to read-write, and then remove the file. + if e.kind() != ErrorKind::PermissionDenied { return Err(e) } + + let attr = match metadata(path) { Ok(a) => a, Err(..) => return Err(e) }; + let mut perms = attr.permissions(); + if !perms.readonly() { return Err(e) } + perms.set_readonly(false); + + if set_permissions(path, perms).is_err() { return Err(e) } + if fs_imp::unlink(path).is_ok() { return Ok(()) } + + // Oops, try to put things back the way we found it + let _ = set_permissions(path, attr.permissions()); + Err(e) +} + +/// Given a path, query the file system to get information about a file, +/// directory, etc. +/// +/// This function will traverse soft links to query information about the +/// destination file. +/// +/// # Example +/// +/// ```rust,no_run +/// # fn foo() -> std::io::Result<()> { +/// use std::fs; +/// +/// let attr = try!(fs::metadata("/some/file/path.txt")); +/// // inspect attr ... +/// # Ok(()) +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return an error if the user lacks the requisite +/// permissions to perform a `metadata` call on the given `path` or if there +/// is no entry in the filesystem at the provided path. +pub fn metadata(path: &P) -> io::Result { + fs_imp::stat(path.as_path()).map(Metadata) +} + +/// Rename a file or directory to a new name. +/// +/// # Example +/// +/// ```rust,no_run +/// use std::fs; +/// +/// fs::rename("foo", "bar"); +/// ``` +/// +/// # Errors +/// +/// This function will return an error if the provided `from` doesn't exist, if +/// the process lacks permissions to view the contents, if `from` and `to` +/// reside on separate filesystems, or if some other intermittent I/O error +/// occurs. +pub fn rename(from: &P, to: &Q) + -> io::Result<()> { + fs_imp::rename(from.as_path(), to.as_path()) +} + +/// Copies the contents of one file to another. This function will also +/// copy the permission bits of the original file to the destination file. +/// +/// This function will **overwrite** the contents of `to`. +/// +/// Note that if `from` and `to` both point to the same file, then the file +/// will likely get truncated by this operation. +/// +/// # Example +/// +/// ```rust +/// use std::fs; +/// +/// fs::copy("foo.txt", "bar.txt"); +/// ``` +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * The `from` path is not a file +/// * The `from` file does not exist +/// * The current process does not have the permission rights to access +/// `from` or write `to` +pub fn copy(from: &P, to: &Q) + -> io::Result { + let from = from.as_path(); + if !from.is_file() { + return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation, + "the source path is not an existing file", + None)) + } + + let mut reader = try!(File::open(from)); + let mut writer = try!(File::create(to)); + let perm = try!(reader.metadata()).permissions(); + + let ret = try!(io::copy(&mut reader, &mut writer)); + try!(set_permissions(to, perm)); + Ok(ret) +} + +/// Creates a new hard link on the filesystem. +/// +/// The `dst` path will be a link pointing to the `src` path. Note that systems +/// often require these two paths to both be located on the same filesystem. +pub fn hard_link(src: &P, dst: &Q) + -> io::Result<()> { + fs_imp::link(src.as_path(), dst.as_path()) +} + +/// Creates a new soft link on the filesystem. +/// +/// The `dst` path will be a soft link pointing to the `src` path. +pub fn soft_link(src: &P, dst: &Q) + -> io::Result<()> { + fs_imp::symlink(src.as_path(), dst.as_path()) +} + +/// Reads a soft link, returning the file that the link points to. +/// +/// # Errors +/// +/// This function will return an error on failure. Failure conditions include +/// reading a file that does not exist or reading a file that is not a soft +/// link. +pub fn read_link(path: &P) -> io::Result { + fs_imp::readlink(path.as_path()) +} + +/// Create a new, empty directory at the provided path +/// +/// # Example +/// +/// ```rust +/// use std::fs; +/// +/// fs::create_dir("/some/dir"); +/// ``` +/// +/// # Errors +/// +/// This function will return an error if the user lacks permissions to make a +/// new directory at the provided `path`, or if the directory already exists. +pub fn create_dir(path: &P) -> io::Result<()> { + fs_imp::mkdir(path.as_path()) +} + +/// Recursively create a directory and all of its parent components if they +/// are missing. +/// +/// # Errors +/// +/// This function will fail if any directory in the path specified by `path` +/// does not already exist and it could not be created otherwise. The specific +/// error conditions for when a directory is being created (after it is +/// determined to not exist) are outlined by `fs::create_dir`. +pub fn create_dir_all(path: &P) -> io::Result<()> { + let path = path.as_path(); + if path.is_dir() { return Ok(()) } + match path.parent() { + Some(p) if p != path => try!(create_dir_all(p)), + _ => {} + } + create_dir(path) +} + +/// Remove an existing, empty directory +/// +/// # Example +/// +/// ```rust +/// use std::fs; +/// +/// fs::remove_dir("/some/dir"); +/// ``` +/// +/// # Errors +/// +/// This function will return an error if the user lacks permissions to remove +/// the directory at the provided `path`, or if the directory isn't empty. +pub fn remove_dir(path: &P) -> io::Result<()> { + fs_imp::rmdir(path.as_path()) +} + +/// Removes a directory at this path, after removing all its contents. Use +/// carefully! +/// +/// This function does **not** follow soft links and it will simply remove the +/// soft link itself. +/// +/// # Errors +/// +/// See `file::remove_file` and `fs::remove_dir` +pub fn remove_dir_all(path: &P) -> io::Result<()> { + let path = path.as_path(); + for child in try!(read_dir(path)) { + let child = try!(child).path(); + let stat = try!(lstat(&*child)); + if stat.is_dir() { + try!(remove_dir_all(&*child)); + } else { + try!(remove_file(&*child)); + } + } + return remove_dir(path); + + #[cfg(unix)] + fn lstat(path: &Path) -> io::Result { fs_imp::lstat(path) } + #[cfg(windows)] + fn lstat(path: &Path) -> io::Result { fs_imp::stat(path) } +} + +/// Returns an iterator over the entries within a directory. +/// +/// The iterator will yield instances of `io::Result`. New errors may +/// be encountered after an iterator is initially constructed. +/// +/// # Example +/// +/// ```rust +/// use std::io; +/// use std::fs::{self, PathExt, DirEntry}; +/// use std::path::Path; +/// +/// // one possible implementation of fs::walk_dir only visiting files +/// fn visit_dirs(dir: &Path, cb: &mut FnMut(DirEntry)) -> io::Result<()> { +/// if dir.is_dir() { +/// for entry in try!(fs::read_dir(dir)) { +/// let entry = try!(entry); +/// if entry.path().is_dir() { +/// try!(visit_dirs(&entry.path(), cb)); +/// } else { +/// cb(entry); +/// } +/// } +/// } +/// Ok(()) +/// } +/// ``` +/// +/// # Errors +/// +/// This function will return an error if the provided `path` doesn't exist, if +/// the process lacks permissions to view the contents or if the `path` points +/// at a non-directory file +pub fn read_dir(path: &P) -> io::Result { + fs_imp::readdir(path.as_path()).map(ReadDir) +} + +/// Returns an iterator that will recursively walk the directory structure +/// rooted at `path`. +/// +/// The path given will not be iterated over, and this will perform iteration in +/// some top-down order. The contents of unreadable subdirectories are ignored. +/// +/// The iterator will yield instances of `io::Result`. New errors may +/// be encountered after an iterator is initially constructed. +pub fn walk_dir(path: &P) -> io::Result { + let start = try!(read_dir(path)); + Ok(WalkDir { cur: Some(start), stack: Vec::new() }) +} + +impl Iterator for WalkDir { + type Item = io::Result; + + fn next(&mut self) -> Option> { + loop { + if let Some(ref mut cur) = self.cur { + match cur.next() { + Some(Err(e)) => return Some(Err(e)), + Some(Ok(next)) => { + let path = next.path(); + if path.is_dir() { + self.stack.push(read_dir(&*path)); + } + return Some(Ok(next)) + } + None => {} + } + } + self.cur = None; + match self.stack.pop() { + Some(Err(e)) => return Some(Err(e)), + Some(Ok(next)) => self.cur = Some(next), + None => return None, + } + } + } +} + +/// Utility methods for paths. +pub trait PathExt { + /// Get information on the file, directory, etc at this path. + /// + /// Consult the `fs::stat` documentation for more info. + /// + /// This call preserves identical runtime/error semantics with `file::stat`. + fn metadata(&self) -> io::Result; + + /// Boolean value indicator whether the underlying file exists on the local + /// filesystem. Returns false in exactly the cases where `fs::stat` fails. + fn exists(&self) -> bool; + + /// Whether the underlying implementation (be it a file path, or something + /// else) points at a "regular file" on the FS. Will return false for paths + /// to non-existent locations or directories or other non-regular files + /// (named pipes, etc). Follows links when making this determination. + fn is_file(&self) -> bool; + + /// Whether the underlying implementation (be it a file path, or something + /// else) is pointing at a directory in the underlying FS. Will return + /// false for paths to non-existent locations or if the item is not a + /// directory (eg files, named pipes, etc). Follows links when making this + /// determination. + fn is_dir(&self) -> bool; +} + +impl PathExt for Path { + fn metadata(&self) -> io::Result { metadata(self) } + + fn exists(&self) -> bool { metadata(self).is_ok() } + + fn is_file(&self) -> bool { + metadata(self).map(|s| s.is_file()).unwrap_or(false) + } + fn is_dir(&self) -> bool { + metadata(self).map(|s| s.is_dir()).unwrap_or(false) + } +} + +/// Changes the timestamps for a file's last modification and access time. +/// +/// The file at the path specified will have its last access time set to +/// `atime` and its modification time set to `mtime`. The times specified should +/// be in milliseconds. +pub fn set_file_times(path: &P, accessed: u64, + modified: u64) -> io::Result<()> { + fs_imp::utimes(path.as_path(), accessed, modified) +} + +/// Changes the permissions found on a file or a directory. +/// +/// # Example +/// +/// ``` +/// # fn foo() -> std::io::Result<()> { +/// use std::fs; +/// +/// let mut perms = try!(fs::metadata("foo.txt")).permissions(); +/// perms.set_readonly(true); +/// try!(fs::set_permissions("foo.txt", perms)); +/// # Ok(()) +/// # } +/// ``` +/// +/// # Errors +/// +/// This function will return an error if the provided `path` doesn't exist, if +/// the process lacks permissions to change the attributes of the file, or if +/// some other I/O error is encountered. +pub fn set_permissions(path: &P, perm: Permissions) + -> io::Result<()> { + fs_imp::set_perm(path.as_path(), perm.0) +} + +#[cfg(test)] +mod tests { + #![allow(deprecated)] //rand + + use prelude::v1::*; + use io::prelude::*; + + use fs::{self, File, OpenOptions}; + use io::{ErrorKind, SeekFrom}; + use path::PathBuf; + use path::Path as Path2; + use os; + use rand::{self, StdRng, Rng}; + use str; + + macro_rules! check { ($e:expr) => ( + match $e { + Ok(t) => t, + Err(e) => panic!("{} failed with: {}", stringify!($e), e), + } + ) } + + macro_rules! error { ($e:expr, $s:expr) => ( + match $e { + Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), + Err(ref err) => assert!(err.to_string().contains($s.as_slice()), + format!("`{}` did not contain `{}`", err, $s)) + } + ) } + + pub struct TempDir(PathBuf); + + impl TempDir { + fn join(&self, path: &str) -> PathBuf { + let TempDir(ref p) = *self; + p.join(path) + } + + fn path<'a>(&'a self) -> &'a Path2 { + let TempDir(ref p) = *self; + p + } + } + + impl Drop for TempDir { + fn drop(&mut self) { + // Gee, seeing how we're testing the fs module I sure hope that we + // at least implement this correctly! + let TempDir(ref p) = *self; + check!(fs::remove_dir_all(p)); + } + } + + pub fn tmpdir() -> TempDir { + let s = os::tmpdir(); + let p = Path2::new(s.as_str().unwrap()); + let ret = p.join(&format!("rust-{}", rand::random::())); + check!(fs::create_dir(&ret)); + TempDir(ret) + } + + #[test] + fn file_test_io_smoke_test() { + let message = "it's alright. have a good time"; + let tmpdir = tmpdir(); + let filename = &tmpdir.join("file_rt_io_file_test.txt"); + { + let mut write_stream = check!(File::create(filename)); + check!(write_stream.write(message.as_bytes())); + } + { + let mut read_stream = check!(File::open(filename)); + let mut read_buf = [0; 1028]; + let read_str = match check!(read_stream.read(&mut read_buf)) { + -1|0 => panic!("shouldn't happen"), + n => str::from_utf8(&read_buf[..n]).unwrap().to_string() + }; + assert_eq!(read_str.as_slice(), message); + } + check!(fs::remove_file(filename)); + } + + #[test] + fn invalid_path_raises() { + let tmpdir = tmpdir(); + let filename = &tmpdir.join("file_that_does_not_exist.txt"); + let result = File::open(filename); + + if cfg!(unix) { + error!(result, "o such file or directory"); + } + // error!(result, "couldn't open path as file"); + // error!(result, format!("path={}; mode=open; access=read", filename.display())); + } + + #[test] + fn file_test_iounlinking_invalid_path_should_raise_condition() { + let tmpdir = tmpdir(); + let filename = &tmpdir.join("file_another_file_that_does_not_exist.txt"); + + let result = fs::remove_file(filename); + + if cfg!(unix) { + error!(result, "o such file or directory"); + } + // error!(result, "couldn't unlink path"); + // error!(result, format!("path={}", filename.display())); + } + + #[test] + fn file_test_io_non_positional_read() { + let message: &str = "ten-four"; + let mut read_mem = [0; 8]; + let tmpdir = tmpdir(); + let filename = &tmpdir.join("file_rt_io_file_test_positional.txt"); + { + let mut rw_stream = check!(File::create(filename)); + check!(rw_stream.write(message.as_bytes())); + } + { + let mut read_stream = check!(File::open(filename)); + { + let read_buf = &mut read_mem[0..4]; + check!(read_stream.read(read_buf)); + } + { + let read_buf = &mut read_mem[4..8]; + check!(read_stream.read(read_buf)); + } + } + check!(fs::remove_file(filename)); + let read_str = str::from_utf8(&read_mem).unwrap(); + assert_eq!(read_str, message); + } + + #[test] + fn file_test_io_seek_and_tell_smoke_test() { + let message = "ten-four"; + let mut read_mem = [0; 4]; + let set_cursor = 4 as u64; + let mut tell_pos_pre_read; + let mut tell_pos_post_read; + let tmpdir = tmpdir(); + let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt"); + { + let mut rw_stream = check!(File::create(filename)); + check!(rw_stream.write(message.as_bytes())); + } + { + let mut read_stream = check!(File::open(filename)); + check!(read_stream.seek(SeekFrom::Start(set_cursor))); + tell_pos_pre_read = check!(read_stream.seek(SeekFrom::Current(0))); + check!(read_stream.read(&mut read_mem)); + tell_pos_post_read = check!(read_stream.seek(SeekFrom::Current(0))); + } + check!(fs::remove_file(filename)); + let read_str = str::from_utf8(&read_mem).unwrap(); + assert_eq!(read_str, &message[4..8]); + assert_eq!(tell_pos_pre_read, set_cursor); + assert_eq!(tell_pos_post_read, message.len() as u64); + } + + #[test] + fn file_test_io_seek_and_write() { + let initial_msg = "food-is-yummy"; + let overwrite_msg = "-the-bar!!"; + let final_msg = "foo-the-bar!!"; + let seek_idx = 3; + let mut read_mem = [0; 13]; + let tmpdir = tmpdir(); + let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt"); + { + let mut rw_stream = check!(File::create(filename)); + check!(rw_stream.write(initial_msg.as_bytes())); + check!(rw_stream.seek(SeekFrom::Start(seek_idx))); + check!(rw_stream.write(overwrite_msg.as_bytes())); + } + { + let mut read_stream = check!(File::open(filename)); + check!(read_stream.read(&mut read_mem)); + } + check!(fs::remove_file(filename)); + let read_str = str::from_utf8(&read_mem).unwrap(); + assert!(read_str == final_msg); + } + + #[test] + fn file_test_io_seek_shakedown() { + // 01234567890123 + let initial_msg = "qwer-asdf-zxcv"; + let chunk_one: &str = "qwer"; + let chunk_two: &str = "asdf"; + let chunk_three: &str = "zxcv"; + let mut read_mem = [0; 4]; + let tmpdir = tmpdir(); + let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt"); + { + let mut rw_stream = check!(File::create(filename)); + check!(rw_stream.write(initial_msg.as_bytes())); + } + { + let mut read_stream = check!(File::open(filename)); + + check!(read_stream.seek(SeekFrom::End(-4))); + check!(read_stream.read(&mut read_mem)); + assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_three); + + check!(read_stream.seek(SeekFrom::Current(-9))); + check!(read_stream.read(&mut read_mem)); + assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_two); + + check!(read_stream.seek(SeekFrom::Start(0))); + check!(read_stream.read(&mut read_mem)); + assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_one); + } + check!(fs::remove_file(filename)); + } + + #[test] + fn file_test_stat_is_correct_on_is_file() { + let tmpdir = tmpdir(); + let filename = &tmpdir.join("file_stat_correct_on_is_file.txt"); + { + let mut opts = OpenOptions::new(); + let mut fs = check!(opts.read(true).write(true) + .create(true).open(filename)); + let msg = "hw"; + fs.write(msg.as_bytes()).unwrap(); + + let fstat_res = check!(fs.metadata()); + assert!(fstat_res.is_file()); + } + let stat_res_fn = check!(fs::metadata(filename)); + assert!(stat_res_fn.is_file()); + let stat_res_meth = check!(filename.metadata()); + assert!(stat_res_meth.is_file()); + check!(fs::remove_file(filename)); + } + + #[test] + fn file_test_stat_is_correct_on_is_dir() { + let tmpdir = tmpdir(); + let filename = &tmpdir.join("file_stat_correct_on_is_dir"); + check!(fs::create_dir(filename)); + let stat_res_fn = check!(fs::metadata(filename)); + assert!(stat_res_fn.is_dir()); + let stat_res_meth = check!(filename.metadata()); + assert!(stat_res_meth.is_dir()); + check!(fs::remove_dir(filename)); + } + + #[test] + fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() { + let tmpdir = tmpdir(); + let dir = &tmpdir.join("fileinfo_false_on_dir"); + check!(fs::create_dir(dir)); + assert!(dir.is_file() == false); + check!(fs::remove_dir(dir)); + } + + #[test] + fn file_test_fileinfo_check_exists_before_and_after_file_creation() { + let tmpdir = tmpdir(); + let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt"); + check!(check!(File::create(file)).write(b"foo")); + assert!(file.exists()); + check!(fs::remove_file(file)); + assert!(!file.exists()); + } + + #[test] + fn file_test_directoryinfo_check_exists_before_and_after_mkdir() { + let tmpdir = tmpdir(); + let dir = &tmpdir.join("before_and_after_dir"); + assert!(!dir.exists()); + check!(fs::create_dir(dir)); + assert!(dir.exists()); + assert!(dir.is_dir()); + check!(fs::remove_dir(dir)); + assert!(!dir.exists()); + } + + #[test] + fn file_test_directoryinfo_readdir() { + let tmpdir = tmpdir(); + let dir = &tmpdir.join("di_readdir"); + check!(fs::create_dir(dir)); + let prefix = "foo"; + for n in range(0, 3) { + let f = dir.join(&format!("{}.txt", n)); + let mut w = check!(File::create(&f)); + let msg_str = format!("{}{}", prefix, n.to_string()); + let msg = msg_str.as_bytes(); + check!(w.write(msg)); + } + let files = check!(fs::read_dir(dir)); + let mut mem = [0u8; 4]; + for f in files { + let f = f.unwrap().path(); + { + let n = f.file_stem().unwrap(); + check!(check!(File::open(&f)).read(&mut mem)); + let read_str = str::from_utf8(&mem).unwrap(); + let expected = format!("{}{}", prefix, n.to_str().unwrap()); + assert_eq!(expected.as_slice(), read_str); + } + check!(fs::remove_file(&f)); + } + check!(fs::remove_dir(dir)); + } + + #[test] + fn file_test_walk_dir() { + let tmpdir = tmpdir(); + let dir = &tmpdir.join("walk_dir"); + check!(fs::create_dir(dir)); + + let dir1 = &dir.join("01/02/03"); + check!(fs::create_dir_all(dir1)); + check!(File::create(&dir1.join("04"))); + + let dir2 = &dir.join("11/12/13"); + check!(fs::create_dir_all(dir2)); + check!(File::create(&dir2.join("14"))); + + let files = check!(fs::walk_dir(dir)); + let mut cur = [0u8; 2]; + for f in files { + let f = f.unwrap().path(); + let stem = f.file_stem().unwrap().to_str().unwrap(); + let root = stem.as_bytes()[0] - b'0'; + let name = stem.as_bytes()[1] - b'0'; + assert!(cur[root as usize] < name); + cur[root as usize] = name; + } + + check!(fs::remove_dir_all(dir)); + } + + #[test] + fn mkdir_path_already_exists_error() { + let tmpdir = tmpdir(); + let dir = &tmpdir.join("mkdir_error_twice"); + check!(fs::create_dir(dir)); + let e = fs::create_dir(dir).err().unwrap(); + assert_eq!(e.kind(), ErrorKind::PathAlreadyExists); + } + + #[test] + fn recursive_mkdir() { + let tmpdir = tmpdir(); + let dir = tmpdir.join("d1/d2"); + check!(fs::create_dir_all(&dir)); + assert!(dir.is_dir()) + } + + #[test] + fn recursive_mkdir_failure() { + let tmpdir = tmpdir(); + let dir = tmpdir.join("d1"); + let file = dir.join("f1"); + + check!(fs::create_dir_all(&dir)); + check!(File::create(&file)); + + let result = fs::create_dir_all(&file); + + assert!(result.is_err()); + // error!(result, "couldn't recursively mkdir"); + // error!(result, "couldn't create directory"); + // error!(result, "mode=0700"); + // error!(result, format!("path={}", file.display())); + } + + #[test] + fn recursive_mkdir_slash() { + check!(fs::create_dir_all(&Path2::new("/"))); + } + + // FIXME(#12795) depends on lstat to work on windows + #[cfg(not(windows))] + #[test] + fn recursive_rmdir() { + let tmpdir = tmpdir(); + let d1 = tmpdir.join("d1"); + let dt = d1.join("t"); + let dtt = dt.join("t"); + let d2 = tmpdir.join("d2"); + let canary = d2.join("do_not_delete"); + check!(fs::create_dir_all(&dtt)); + check!(fs::create_dir_all(&d2)); + check!(check!(File::create(&canary)).write(b"foo")); + check!(fs::soft_link(&d2, &dt.join("d2"))); + check!(fs::remove_dir_all(&d1)); + + assert!(!d1.is_dir()); + assert!(canary.exists()); + } + + #[test] + fn unicode_path_is_dir() { + assert!(Path2::new(".").is_dir()); + assert!(!Path2::new("test/stdtest/fs.rs").is_dir()); + + let tmpdir = tmpdir(); + + let mut dirpath = tmpdir.path().to_path_buf(); + dirpath.push(&format!("test-가一ー你好")); + check!(fs::create_dir(&dirpath)); + assert!(dirpath.is_dir()); + + let mut filepath = dirpath; + filepath.push("unicode-file-\u{ac00}\u{4e00}\u{30fc}\u{4f60}\u{597d}.rs"); + check!(File::create(&filepath)); // ignore return; touch only + assert!(!filepath.is_dir()); + assert!(filepath.exists()); + } + + #[test] + fn unicode_path_exists() { + assert!(Path2::new(".").exists()); + assert!(!Path2::new("test/nonexistent-bogus-path").exists()); + + let tmpdir = tmpdir(); + let unicode = tmpdir.path(); + let unicode = unicode.join(&format!("test-각丁ー再见")); + check!(fs::create_dir(&unicode)); + assert!(unicode.exists()); + assert!(!Path2::new("test/unicode-bogus-path-각丁ー再见").exists()); + } + + #[test] + fn copy_file_does_not_exist() { + let from = Path2::new("test/nonexistent-bogus-path"); + let to = Path2::new("test/other-bogus-path"); + + match fs::copy(&from, &to) { + Ok(..) => panic!(), + Err(..) => { + assert!(!from.exists()); + assert!(!to.exists()); + } + } + } + + #[test] + fn copy_file_ok() { + let tmpdir = tmpdir(); + let input = tmpdir.join("in.txt"); + let out = tmpdir.join("out.txt"); + + check!(check!(File::create(&input)).write(b"hello")); + check!(fs::copy(&input, &out)); + let mut v = Vec::new(); + check!(check!(File::open(&out)).read_to_end(&mut v)); + assert_eq!(v.as_slice(), b"hello"); + + assert_eq!(check!(input.metadata()).permissions(), + check!(out.metadata()).permissions()); + } + + #[test] + fn copy_file_dst_dir() { + let tmpdir = tmpdir(); + let out = tmpdir.join("out"); + + check!(File::create(&out)); + match fs::copy(&*out, tmpdir.path()) { + Ok(..) => panic!(), Err(..) => {} + } + } + + #[test] + fn copy_file_dst_exists() { + let tmpdir = tmpdir(); + let input = tmpdir.join("in"); + let output = tmpdir.join("out"); + + check!(check!(File::create(&input)).write("foo".as_bytes())); + check!(check!(File::create(&output)).write("bar".as_bytes())); + check!(fs::copy(&input, &output)); + + let mut v = Vec::new(); + check!(check!(File::open(&output)).read_to_end(&mut v)); + assert_eq!(v, b"foo".to_vec()); + } + + #[test] + fn copy_file_src_dir() { + let tmpdir = tmpdir(); + let out = tmpdir.join("out"); + + match fs::copy(tmpdir.path(), &out) { + Ok(..) => panic!(), Err(..) => {} + } + assert!(!out.exists()); + } + + #[test] + fn copy_file_preserves_perm_bits() { + let tmpdir = tmpdir(); + let input = tmpdir.join("in.txt"); + let out = tmpdir.join("out.txt"); + + let attr = check!(check!(File::create(&input)).metadata()); + let mut p = attr.permissions(); + p.set_readonly(true); + check!(fs::set_permissions(&input, p)); + check!(fs::copy(&input, &out)); + assert!(check!(out.metadata()).permissions().readonly()); + } + + #[cfg(not(windows))] // FIXME(#10264) operation not permitted? + #[test] + fn symlinks_work() { + let tmpdir = tmpdir(); + let input = tmpdir.join("in.txt"); + let out = tmpdir.join("out.txt"); + + check!(check!(File::create(&input)).write("foobar".as_bytes())); + check!(fs::soft_link(&input, &out)); + // if cfg!(not(windows)) { + // assert_eq!(check!(lstat(&out)).kind, FileType::Symlink); + // assert_eq!(check!(out.lstat()).kind, FileType::Symlink); + // } + assert_eq!(check!(fs::metadata(&out)).len(), + check!(fs::metadata(&input)).len()); + let mut v = Vec::new(); + check!(check!(File::open(&out)).read_to_end(&mut v)); + assert_eq!(v, b"foobar".to_vec()); + } + + #[cfg(not(windows))] // apparently windows doesn't like symlinks + #[test] + fn symlink_noexist() { + let tmpdir = tmpdir(); + // symlinks can point to things that don't exist + check!(fs::soft_link(&tmpdir.join("foo"), &tmpdir.join("bar"))); + assert_eq!(check!(fs::read_link(&tmpdir.join("bar"))), + tmpdir.join("foo")); + } + + #[test] + fn readlink_not_symlink() { + let tmpdir = tmpdir(); + match fs::read_link(tmpdir.path()) { + Ok(..) => panic!("wanted a failure"), + Err(..) => {} + } + } + + #[test] + fn links_work() { + let tmpdir = tmpdir(); + let input = tmpdir.join("in.txt"); + let out = tmpdir.join("out.txt"); + + check!(check!(File::create(&input)).write("foobar".as_bytes())); + check!(fs::hard_link(&input, &out)); + assert_eq!(check!(fs::metadata(&out)).len(), + check!(fs::metadata(&input)).len()); + assert_eq!(check!(fs::metadata(&out)).len(), + check!(input.metadata()).len()); + let mut v = Vec::new(); + check!(check!(File::open(&out)).read_to_end(&mut v)); + assert_eq!(v, b"foobar".to_vec()); + + // can't link to yourself + match fs::hard_link(&input, &input) { + Ok(..) => panic!("wanted a failure"), + Err(..) => {} + } + // can't link to something that doesn't exist + match fs::hard_link(&tmpdir.join("foo"), &tmpdir.join("bar")) { + Ok(..) => panic!("wanted a failure"), + Err(..) => {} + } + } + + #[test] + fn chmod_works() { + let tmpdir = tmpdir(); + let file = tmpdir.join("in.txt"); + + check!(File::create(&file)); + let attr = check!(fs::metadata(&file)); + assert!(!attr.permissions().readonly()); + let mut p = attr.permissions(); + p.set_readonly(true); + check!(fs::set_permissions(&file, p.clone())); + let attr = check!(fs::metadata(&file)); + assert!(attr.permissions().readonly()); + + match fs::set_permissions(&tmpdir.join("foo"), p) { + Ok(..) => panic!("wanted a panic"), + Err(..) => {} + } + } + + #[test] + fn sync_doesnt_kill_anything() { + let tmpdir = tmpdir(); + let path = tmpdir.join("in.txt"); + + let mut file = check!(File::create(&path)); + check!(file.sync_all()); + check!(file.sync_data()); + check!(file.write(b"foo")); + check!(file.sync_all()); + check!(file.sync_data()); + } + + #[test] + fn truncate_works() { + let tmpdir = tmpdir(); + let path = tmpdir.join("in.txt"); + + let mut file = check!(File::create(&path)); + check!(file.write(b"foo")); + check!(file.sync_all()); + + // Do some simple things with truncation + assert_eq!(check!(file.metadata()).len(), 3); + check!(file.set_len(10)); + assert_eq!(check!(file.metadata()).len(), 10); + check!(file.write(b"bar")); + check!(file.sync_all()); + assert_eq!(check!(file.metadata()).len(), 10); + + let mut v = Vec::new(); + check!(check!(File::open(&path)).read_to_end(&mut v)); + assert_eq!(v, b"foobar\0\0\0\0".to_vec()); + + // Truncate to a smaller length, don't seek, and then write something. + // Ensure that the intermediate zeroes are all filled in (we're seeked + // past the end of the file). + check!(file.set_len(2)); + assert_eq!(check!(file.metadata()).len(), 2); + check!(file.write(b"wut")); + check!(file.sync_all()); + assert_eq!(check!(file.metadata()).len(), 9); + let mut v = Vec::new(); + check!(check!(File::open(&path)).read_to_end(&mut v)); + assert_eq!(v, b"fo\0\0\0\0wut".to_vec()); + } + + #[test] + fn open_flavors() { + use fs::OpenOptions as OO; + fn c(t: &T) -> T { t.clone() } + + let tmpdir = tmpdir(); + + let mut r = OO::new(); r.read(true); + let mut w = OO::new(); w.write(true); + let mut rw = OO::new(); rw.write(true).read(true); + + match r.open(&tmpdir.join("a")) { + Ok(..) => panic!(), Err(..) => {} + } + + // Perform each one twice to make sure that it succeeds the second time + // (where the file exists) + check!(c(&w).create(true).open(&tmpdir.join("b"))); + assert!(tmpdir.join("b").exists()); + check!(c(&w).create(true).open(&tmpdir.join("b"))); + check!(w.open(&tmpdir.join("b"))); + + check!(c(&rw).create(true).open(&tmpdir.join("c"))); + assert!(tmpdir.join("c").exists()); + check!(c(&rw).create(true).open(&tmpdir.join("c"))); + check!(rw.open(&tmpdir.join("c"))); + + check!(c(&w).append(true).create(true).open(&tmpdir.join("d"))); + assert!(tmpdir.join("d").exists()); + check!(c(&w).append(true).create(true).open(&tmpdir.join("d"))); + check!(c(&w).append(true).open(&tmpdir.join("d"))); + + check!(c(&rw).append(true).create(true).open(&tmpdir.join("e"))); + assert!(tmpdir.join("e").exists()); + check!(c(&rw).append(true).create(true).open(&tmpdir.join("e"))); + check!(c(&rw).append(true).open(&tmpdir.join("e"))); + + check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f"))); + assert!(tmpdir.join("f").exists()); + check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f"))); + check!(c(&w).truncate(true).open(&tmpdir.join("f"))); + + check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g"))); + assert!(tmpdir.join("g").exists()); + check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g"))); + check!(c(&rw).truncate(true).open(&tmpdir.join("g"))); + + check!(check!(File::create(&tmpdir.join("h"))).write("foo".as_bytes())); + check!(r.open(&tmpdir.join("h"))); + { + let mut f = check!(r.open(&tmpdir.join("h"))); + assert!(f.write("wut".as_bytes()).is_err()); + } + assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3); + { + let mut f = check!(c(&w).append(true).open(&tmpdir.join("h"))); + check!(f.write("bar".as_bytes())); + } + assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 6); + { + let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h"))); + check!(f.write("bar".as_bytes())); + } + assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3); + } + + #[test] + fn utime() { + let tmpdir = tmpdir(); + let path = tmpdir.join("a"); + check!(File::create(&path)); + // These numbers have to be bigger than the time in the day to account + // for timezones Windows in particular will fail in certain timezones + // with small enough values + check!(fs::set_file_times(&path, 100000, 200000)); + assert_eq!(check!(path.metadata()).accessed(), 100000); + assert_eq!(check!(path.metadata()).modified(), 200000); + } + + #[test] + fn utime_noexist() { + let tmpdir = tmpdir(); + + match fs::set_file_times(&tmpdir.join("a"), 100, 200) { + Ok(..) => panic!(), + Err(..) => {} + } + } + + #[test] + fn binary_file() { + let mut bytes = [0; 1024]; + StdRng::new().ok().unwrap().fill_bytes(&mut bytes); + + let tmpdir = tmpdir(); + + check!(check!(File::create(&tmpdir.join("test"))).write(&bytes)); + let mut v = Vec::new(); + check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v)); + assert!(v == bytes.as_slice()); + } + + #[test] + fn unlink_readonly() { + let tmpdir = tmpdir(); + let path = tmpdir.join("file"); + check!(File::create(&path)); + let mut perm = check!(fs::metadata(&path)).permissions(); + perm.set_readonly(true); + check!(fs::set_permissions(&path, perm)); + check!(fs::remove_file(&path)); + } +} diff --git a/src/libstd/fs/tempdir.rs b/src/libstd/fs/tempdir.rs new file mode 100644 index 00000000000..79bdb35dd48 --- /dev/null +++ b/src/libstd/fs/tempdir.rs @@ -0,0 +1,125 @@ +// 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. + +#![unstable(feature = "tempdir", reason = "needs an RFC before stabilization")] + +use prelude::v1::*; + +use env; +use io::{self, Error, ErrorKind}; +use fs; +use path::{self, PathBuf, AsPath}; +use rand::{thread_rng, Rng}; + +/// A wrapper for a path to temporary directory implementing automatic +/// scope-based deletion. +pub struct TempDir { + path: Option, +} + +// How many times should we (re)try finding an unused random name? It should be +// enough that an attacker will run out of luck before we run out of patience. +const NUM_RETRIES: u32 = 1 << 31; +// How many characters should we include in a random file name? It needs to +// be enough to dissuade an attacker from trying to preemptively create names +// of that length, but not so huge that we unnecessarily drain the random number +// generator of entropy. +const NUM_RAND_CHARS: uint = 12; + +impl TempDir { + /// Attempts to make a temporary directory inside of `tmpdir` whose name + /// will have the prefix `prefix`. The directory will be automatically + /// deleted once the returned wrapper is destroyed. + /// + /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] // rand usage + pub fn new_in(tmpdir: &P, prefix: &str) + -> io::Result { + let storage; + let mut tmpdir = tmpdir.as_path(); + if !tmpdir.is_absolute() { + let cur_dir = try!(env::current_dir()); + storage = cur_dir.join(tmpdir); + tmpdir = &storage; + // return TempDir::new_in(&cur_dir.join(tmpdir), prefix); + } + + let mut rng = thread_rng(); + for _ in 0..NUM_RETRIES { + let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect(); + let leaf = if prefix.len() > 0 { + format!("{}.{}", prefix, suffix) + } else { + // If we're given an empty string for a prefix, then creating a + // directory starting with "." would lead to it being + // semi-invisible on some systems. + suffix + }; + let path = tmpdir.join(&leaf); + match fs::create_dir(&path) { + Ok(_) => return Ok(TempDir { path: Some(path) }), + Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {} + Err(e) => return Err(e) + } + } + + Err(Error::new(ErrorKind::PathAlreadyExists, + "too many temporary directories already exist", + None)) + } + + /// Attempts to make a temporary directory inside of `env::temp_dir()` whose + /// name will have the prefix `prefix`. The directory will be automatically + /// deleted once the returned wrapper is destroyed. + /// + /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] + pub fn new(prefix: &str) -> io::Result { + TempDir::new_in(&env::temp_dir(), prefix) + } + + /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. + /// This discards the wrapper so that the automatic deletion of the + /// temporary directory is prevented. + pub fn into_path(mut self) -> PathBuf { + self.path.take().unwrap() + } + + /// Access the wrapped `std::path::Path` to the temporary directory. + pub fn path(&self) -> &path::Path { + self.path.as_ref().unwrap() + } + + /// Close and remove the temporary directory + /// + /// Although `TempDir` removes the directory on drop, in the destructor + /// any errors are ignored. To detect errors cleaning up the temporary + /// directory, call `close` instead. + pub fn close(mut self) -> io::Result<()> { + self.cleanup_dir() + } + + fn cleanup_dir(&mut self) -> io::Result<()> { + match self.path { + Some(ref p) => fs::remove_dir_all(p), + None => Ok(()) + } + } +} + +impl Drop for TempDir { + fn drop(&mut self) { + let _ = self.cleanup_dir(); + } +} + +// the tests for this module need to change the path using change_dir, +// and this doesn't play nicely with other tests so these unit tests are located +// in src/test/run-pass/tempfile.rs diff --git a/src/libstd/net/test.rs b/src/libstd/net/test.rs index c70e92884ac..aec50d638c6 100644 --- a/src/libstd/net/test.rs +++ b/src/libstd/net/test.rs @@ -34,6 +34,6 @@ fn base_port() -> u16 { let dirs = ["32-opt", "32-nopt", "64-opt", "64-nopt", "64-opt-vg", "all-opt", "snap3", "dist"]; dirs.iter().enumerate().find(|&(_, dir)| { - cwd.as_str().unwrap().contains(dir) + cwd.to_str().unwrap().contains(dir) }).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600 } diff --git a/src/libstd/old_io/tempfile.rs b/src/libstd/old_io/tempfile.rs index 42317c7a2d4..76753dca52e 100644 --- a/src/libstd/old_io/tempfile.rs +++ b/src/libstd/old_io/tempfile.rs @@ -96,9 +96,10 @@ impl TempDir { /// deleted once the returned wrapper is destroyed. /// /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult { if !tmpdir.is_absolute() { - let cur_dir = try!(env::current_dir()); + let cur_dir = try!(::os::getcwd()); return TempDir::new_in(&cur_dir.join(tmpdir), prefix); } @@ -132,8 +133,9 @@ impl TempDir { /// deleted once the returned wrapper is destroyed. /// /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] pub fn new(prefix: &str) -> IoResult { - TempDir::new_in(&env::temp_dir(), prefix) + TempDir::new_in(&::os::tmpdir(), prefix) } /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. diff --git a/src/libstd/old_io/test.rs b/src/libstd/old_io/test.rs index ee72beccfa8..43c0b9268a2 100644 --- a/src/libstd/old_io/test.rs +++ b/src/libstd/old_io/test.rs @@ -38,10 +38,11 @@ fn next_test_unix_socket() -> String { /// Get a temporary path which could be the location of a unix socket #[cfg(not(target_os = "ios"))] +#[allow(deprecated)] pub fn next_test_unix() -> Path { let string = next_test_unix_socket(); if cfg!(unix) { - env::temp_dir().join(string) + ::os::tmpdir().join(string) } else { Path::new(format!("{}{}", r"\\.\pipe\", string)) } @@ -88,7 +89,7 @@ fn base_port() -> u16 { // FIXME (#9639): This needs to handle non-utf8 paths let path = env::current_dir().unwrap(); - let path_s = path.as_str().unwrap(); + let path_s = path.to_str().unwrap(); let mut final_base = base; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 86f5c2c356e..9c42d1be77e 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -49,6 +49,7 @@ use ops::{Drop, FnOnce}; use option::Option::{Some, None}; use option::Option; use old_path::{Path, GenericPath, BytesContainer}; +use path::{self, PathBuf}; use ptr::PtrExt; use ptr; use result::Result::{Err, Ok}; @@ -67,6 +68,35 @@ use vec::Vec; #[cfg(unix)] pub use sys::ext as unix; #[cfg(windows)] pub use sys::ext as windows; +fn err2old(new: ::io::Error) -> IoError { + IoError { + kind: ::old_io::OtherIoError, + desc: "os error", + detail: Some(new.to_string()), + } +} + +#[cfg(windows)] +fn path2new(path: &Path) -> PathBuf { + PathBuf::new(path.as_str().unwrap()) +} +#[cfg(unix)] +fn path2new(path: &Path) -> PathBuf { + use os::unix::prelude::*; + PathBuf::new(::from_bytes(path.as_vec())) +} + +#[cfg(unix)] +fn path2old(path: &path::Path) -> Path { + use os::unix::prelude::*; + use ffi::AsOsStr; + Path::new(path.as_os_str().as_bytes()) +} +#[cfg(windows)] +fn path2old(path: &path::Path) -> Path { + Path::new(path.to_str().unwrap()) +} + /// Get the number of cores available pub fn num_cpus() -> uint { unsafe { @@ -100,10 +130,9 @@ pub const TMPBUF_SZ : uint = 1000; /// let current_working_directory = os::getcwd().unwrap(); /// println!("The current directory is {:?}", current_working_directory.display()); /// ``` -#[deprecated(since = "1.0.0", reason = "renamed to std::env::current_dir")] #[unstable(feature = "os")] pub fn getcwd() -> IoResult { - env::current_dir() + env::current_dir().map_err(err2old).map(|s| path2old(&s)) } /// Returns a vector of (variable, value) pairs, for all the environment @@ -245,12 +274,11 @@ pub fn unsetenv(n: &str) { /// None => println!("{} is not defined in the environment.", key) /// } /// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::split_paths")] #[unstable(feature = "os")] pub fn split_paths(unparsed: T) -> Vec { let b = unparsed.container_as_bytes(); let s = str::from_utf8(b).unwrap(); - env::split_paths(s).collect() + env::split_paths(s).map(|s| path2old(&s)).collect() } /// Joins a collection of `Path`s appropriately for the `PATH` @@ -274,7 +302,6 @@ pub fn split_paths(unparsed: T) -> Vec { /// paths.push(Path::new("/home/xyz/bin")); /// os::setenv(key, os::join_paths(paths.as_slice()).unwrap()); /// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::join_paths")] #[unstable(feature = "os")] pub fn join_paths(paths: &[T]) -> Result, &'static str> { env::join_paths(paths.iter().map(|s| { @@ -335,10 +362,9 @@ pub fn dll_filename(base: &str) -> String { /// None => println!("Unable to get the path of this executable!") /// }; /// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::current_exe")] #[unstable(feature = "os")] pub fn self_exe_name() -> Option { - env::current_exe().ok() + env::current_exe().ok().map(|p| path2old(&p)) } /// Optionally returns the filesystem path to the current executable which is @@ -356,10 +382,9 @@ pub fn self_exe_name() -> Option { /// None => println!("Impossible to fetch the path of this executable.") /// }; /// ``` -#[deprecated(since = "1.0.0", reason = "use env::current_exe + dir_path/pop")] #[unstable(feature = "os")] pub fn self_exe_path() -> Option { - env::current_exe().ok().map(|mut p| { p.pop(); p }) + env::current_exe().ok().map(|p| { let mut p = path2old(&p); p.pop(); p }) } /// Optionally returns the path to the current user's home directory if known. @@ -386,9 +411,8 @@ pub fn self_exe_path() -> Option { /// None => println!("Impossible to get your home dir!") /// } /// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::home_dir")] -#[allow(deprecated)] #[unstable(feature = "os")] +#[allow(deprecated)] pub fn homedir() -> Option { #[inline] #[cfg(unix)] @@ -424,9 +448,8 @@ pub fn homedir() -> Option { /// On Windows, returns the value of, in order, the 'TMP', 'TEMP', /// 'USERPROFILE' environment variable if any are set and not the empty /// string. Otherwise, tmpdir returns the path to the Windows directory. -#[deprecated(since = "1.0.0", reason = "renamed to env::temp_dir")] -#[allow(deprecated)] #[unstable(feature = "os")] +#[allow(deprecated)] pub fn tmpdir() -> Path { return lookup(); @@ -488,7 +511,8 @@ pub fn make_absolute(p: &Path) -> IoResult { if p.is_absolute() { Ok(p.clone()) } else { - env::current_dir().map(|mut cwd| { + env::current_dir().map_err(err2old).map(|cwd| { + let mut cwd = path2old(&cwd); cwd.push(p); cwd }) @@ -507,10 +531,9 @@ pub fn make_absolute(p: &Path) -> IoResult { /// assert!(os::change_dir(&root).is_ok()); /// println!("Successfully changed working directory to {}!", root.display()); /// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::set_current_dir")] #[unstable(feature = "os")] pub fn change_dir(p: &Path) -> IoResult<()> { - return sys::os::chdir(p); + sys::os::chdir(&path2new(p)).map_err(err2old) } /// Returns the platform-specific value of errno diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 6f07dea5279..6267792ba74 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -84,8 +84,9 @@ /// all unix platforms we support right now, so it at least gets the job done. use prelude::v1::*; +use os::unix::prelude::*; -use ffi::CStr; +use ffi::{CStr, AsOsStr}; use old_io::IoResult; use libc; use mem; @@ -327,7 +328,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { }; let filename = match selfname { Some(path) => { - let bytes = path.as_vec(); + let bytes = path.as_os_str().as_bytes(); if bytes.len() < LAST_FILENAME.len() { let i = bytes.iter(); for (slot, val) in LAST_FILENAME.iter_mut().zip(i) { diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index d51f907307e..951c091f9f3 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -16,12 +16,13 @@ use os::unix::*; use error::Error as StdError; use ffi::{CString, CStr, OsString, OsStr, AsOsStr}; use fmt; +use io; use iter; use libc::{self, c_int, c_char, c_void}; use mem; -use io; -use old_io::{IoResult, IoError, fs}; +use old_io::{IoError, IoResult}; use ptr; +use path::{self, PathBuf}; use slice; use str; use sys::c; @@ -32,6 +33,14 @@ use vec; const BUF_BYTES: usize = 2048; const TMPBUF_SZ: usize = 128; +fn bytes2path(b: &[u8]) -> PathBuf { + PathBuf::new(::from_bytes(b)) +} + +fn os2path(os: OsString) -> PathBuf { + bytes2path(os.as_bytes()) +} + /// Returns the platform-specific value of errno pub fn errno() -> i32 { #[cfg(any(target_os = "macos", @@ -102,30 +111,30 @@ pub fn error_string(errno: i32) -> String { } } -pub fn getcwd() -> IoResult { +pub fn getcwd() -> io::Result { let mut buf = [0 as c_char; BUF_BYTES]; unsafe { if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() { - Err(IoError::last_error()) + Err(io::Error::last_os_error()) } else { - Ok(Path::new(CStr::from_ptr(buf.as_ptr()).to_bytes())) + Ok(bytes2path(CStr::from_ptr(buf.as_ptr()).to_bytes())) } } } -pub fn chdir(p: &Path) -> IoResult<()> { - let p = CString::new(p.as_vec()).unwrap(); +pub fn chdir(p: &path::Path) -> io::Result<()> { + let p = try!(CString::new(p.as_os_str().as_bytes())); unsafe { match libc::chdir(p.as_ptr()) == (0 as c_int) { true => Ok(()), - false => Err(IoError::last_error()), + false => Err(io::Error::last_os_error()), } } } pub struct SplitPaths<'a> { iter: iter::Map bool>, - fn(&'a [u8]) -> Path>, + fn(&'a [u8]) -> PathBuf>, } pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> { @@ -133,13 +142,13 @@ pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> { let unparsed = unparsed.as_bytes(); SplitPaths { iter: unparsed.split(is_colon as fn(&u8) -> bool) - .map(Path::new as fn(&'a [u8]) -> Path) + .map(bytes2path as fn(&'a [u8]) -> PathBuf) } } impl<'a> Iterator for SplitPaths<'a> { - type Item = Path; - fn next(&mut self) -> Option { self.iter.next() } + type Item = PathBuf; + fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } @@ -200,12 +209,12 @@ pub fn current_exe() -> IoResult { } #[cfg(target_os = "dragonfly")] -pub fn current_exe() -> IoResult { - fs::readlink(&Path::new("/proc/curproc/file")) +pub fn current_exe() -> io::Result { + ::fs::read_link("/proc/curproc/file") } #[cfg(any(target_os = "bitrig", target_os = "openbsd"))] -pub fn current_exe() -> IoResult { +pub fn current_exe() -> io::Result { use sync::{StaticMutex, MUTEX_INIT}; static LOCK: StaticMutex = MUTEX_INIT; @@ -226,8 +235,8 @@ pub fn current_exe() -> IoResult { } #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn current_exe() -> IoResult { - fs::readlink(&Path::new("/proc/self/exe")) +pub fn current_exe() -> io::Result { + ::fs::read_link("/proc/self/exe") } #[cfg(any(target_os = "macos", target_os = "ios"))] @@ -451,22 +460,20 @@ pub fn page_size() -> usize { } } -pub fn temp_dir() -> Path { - getenv("TMPDIR".as_os_str()).map(|p| Path::new(p.into_vec())).unwrap_or_else(|| { +pub fn temp_dir() -> PathBuf { + getenv("TMPDIR".as_os_str()).map(os2path).unwrap_or_else(|| { if cfg!(target_os = "android") { - Path::new("/data/local/tmp") + PathBuf::new("/data/local/tmp") } else { - Path::new("/tmp") + PathBuf::new("/tmp") } }) } -pub fn home_dir() -> Option { +pub fn home_dir() -> Option { return getenv("HOME".as_os_str()).or_else(|| unsafe { fallback() - }).map(|os| { - Path::new(os.into_vec()) - }); + }).map(os2path); #[cfg(any(target_os = "android", target_os = "ios"))] diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 304d7e01532..309d6c9dc48 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -368,7 +368,9 @@ pub fn readlink(p: &Path) -> IoResult { buf as *const u16, sz - 1, libc::VOLUME_NAME_DOS) - }, super::os2path); + }, |data| { + Path::new(String::from_utf16(data).unwrap()) + }); assert!(unsafe { libc::CloseHandle(handle) } != 0); return ret; } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index a756fb29f81..51df18d504d 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -14,13 +14,14 @@ use prelude::v1::*; -use ffi::OsStr; +use ffi::{OsStr, OsString}; use io::{self, ErrorKind}; use libc; use mem; -use old_io::{self, IoResult, IoError}; use num::Int; -use os::windows::OsStrExt; +use old_io::{self, IoResult, IoError}; +use os::windows::{OsStrExt, OsStringExt}; +use path::PathBuf; use sync::{Once, ONCE_INIT}; macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( @@ -314,9 +315,10 @@ fn fill_utf16_buf_new(f1: F1, f2: F2) -> io::Result fill_utf16_buf_base(f1, f2).map_err(|()| io::Error::last_os_error()) } -fn os2path(s: &[u16]) -> Path { - // FIXME: this should not be a panicking conversion (aka path reform) - Path::new(String::from_utf16(s).unwrap()) +fn os2path(s: &[u16]) -> PathBuf { + let os = ::from_wide(s); + // FIXME(#22751) should consume `os` + PathBuf::new(&os) } pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 6520d30487c..587ab7924fd 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -18,11 +18,13 @@ use os::windows::*; use error::Error as StdError; use ffi::{OsString, OsStr, AsOsStr}; use fmt; -use ops::Range; +use io; use libc::types::os::arch::extra::LPWCH; use libc::{self, c_int, c_void}; use mem; use old_io::{IoError, IoResult}; +use ops::Range; +use path::{self, PathBuf}; use ptr; use slice; use sys::c; @@ -151,8 +153,8 @@ pub fn split_paths(unparsed: &OsStr) -> SplitPaths { } impl<'a> Iterator for SplitPaths<'a> { - type Item = Path; - fn next(&mut self) -> Option { + type Item = PathBuf; + fn next(&mut self) -> Option { // On Windows, the PATH environment variable is semicolon separated. // Double quotes are used as a way of introducing literal semicolons // (since c:\some;dir is a valid Windows path). Double quotes are not @@ -186,7 +188,7 @@ impl<'a> Iterator for SplitPaths<'a> { if !must_yield && in_progress.is_empty() { None } else { - Some(super::os2path(&in_progress[..])) + Some(super::os2path(&in_progress)) } } } @@ -228,33 +230,33 @@ impl StdError for JoinPathsError { fn description(&self) -> &str { "failed to join paths" } } -pub fn current_exe() -> IoResult { - super::fill_utf16_buf(|buf, sz| unsafe { +pub fn current_exe() -> io::Result { + super::fill_utf16_buf_new(|buf, sz| unsafe { libc::GetModuleFileNameW(ptr::null_mut(), buf, sz) }, super::os2path) } -pub fn getcwd() -> IoResult { - super::fill_utf16_buf(|buf, sz| unsafe { +pub fn getcwd() -> io::Result { + super::fill_utf16_buf_new(|buf, sz| unsafe { libc::GetCurrentDirectoryW(sz, buf) }, super::os2path) } -pub fn chdir(p: &Path) -> IoResult<()> { +pub fn chdir(p: &path::Path) -> io::Result<()> { let mut p = p.as_os_str().encode_wide().collect::>(); p.push(0); unsafe { match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) { true => Ok(()), - false => Err(IoError::last_error()), + false => Err(io::Error::last_os_error()), } } } pub fn getenv(k: &OsStr) -> Option { let k = super::to_utf16_os(k); - super::fill_utf16_buf(|buf, sz| unsafe { + super::fill_utf16_buf_new(|buf, sz| unsafe { libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz) }, |buf| { OsStringExt::from_wide(buf) @@ -349,18 +351,18 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { } } -pub fn temp_dir() -> Path { - super::fill_utf16_buf(|buf, sz| unsafe { +pub fn temp_dir() -> PathBuf { + super::fill_utf16_buf_new(|buf, sz| unsafe { c::GetTempPathW(sz, buf) }, super::os2path).unwrap() } -pub fn home_dir() -> Option { +pub fn home_dir() -> Option { getenv("HOME".as_os_str()).or_else(|| { getenv("USERPROFILE".as_os_str()) }).map(|os| { - // FIXME: OsString => Path - Path::new(os.to_str().unwrap()) + // FIXME(#22751) should consume `os` + PathBuf::new(&os) }).or_else(|| unsafe { let me = c::GetCurrentProcess(); let mut token = ptr::null_mut(); @@ -368,7 +370,7 @@ pub fn home_dir() -> Option { return None } let _handle = RawHandle::new(token); - super::fill_utf16_buf(|buf, mut sz| { + super::fill_utf16_buf_new(|buf, mut sz| { match c::GetUserProfileDirectoryW(token, buf, &mut sz) { 0 if libc::GetLastError() != 0 => 0, 0 => sz, diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process2.rs index 19e38196d19..d4c6e85489f 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process2.rs @@ -16,16 +16,15 @@ use collections; use env; use ffi::{OsString, OsStr}; use fmt; +use fs; use io::{self, Error}; use libc::{self, c_void}; -use old_io::fs; -use old_path; use os::windows::OsStrExt; use ptr; use sync::{StaticMutex, MUTEX_INIT}; +use sys::handle::Handle; use sys::pipe2::AnonPipe; use sys::{self, cvt}; -use sys::handle::Handle; use sys_common::{AsInner, FromInner}; //////////////////////////////////////////////////////////////////////////////// @@ -142,9 +141,8 @@ impl Process { for path in split_paths(&v) { let path = path.join(cfg.program.to_str().unwrap()) .with_extension(env::consts::EXE_EXTENSION); - // FIXME: update with new fs module once it lands - if fs::stat(&old_path::Path::new(&path)).is_ok() { - return Some(OsString::from_str(path.as_str().unwrap())) + if fs::metadata(&path).is_ok() { + return Some(path.into_os_string()) } } break diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 5418533aff1..823d2879236 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -60,6 +60,7 @@ #![feature(unicode)] #![feature(std_misc)] #![feature(env)] +#![feature(os)] #![cfg_attr(windows, feature(libc))] #[macro_use] extern crate log; diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs index c40a5534efb..a0cd7842070 100644 --- a/src/libterm/terminfo/searcher.rs +++ b/src/libterm/terminfo/searcher.rs @@ -17,12 +17,13 @@ use std::old_io::fs::PathExtensions; use std::env; /// Return path to database entry for `term` +#[allow(deprecated)] pub fn get_dbpath_for_term(term: &str) -> Option> { if term.len() == 0 { return None; } - let homedir = env::home_dir(); + let homedir = ::std::os::homedir(); let mut dirs_to_search = Vec::new(); let first_char = term.char_at(0); diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs index 0e1ab73c02d..2ab6feaf782 100644 --- a/src/test/run-pass/env-home-dir.rs +++ b/src/test/run-pass/env-home-dir.rs @@ -9,13 +9,14 @@ // except according to those terms. use std::env::*; +use std::path::PathBuf; #[cfg(unix)] fn main() { let oldhome = var("HOME"); set_var("HOME", "/home/MountainView"); - assert!(home_dir() == Some(Path::new("/home/MountainView"))); + assert!(home_dir() == Some(PathBuf::new("/home/MountainView"))); remove_var("HOME"); if cfg!(target_os = "android") { diff --git a/src/test/run-pass/issue-15149.rs b/src/test/run-pass/issue-15149.rs index aa176d5b0f0..d995ecc492e 100644 --- a/src/test/run-pass/issue-15149.rs +++ b/src/test/run-pass/issue-15149.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - // 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. @@ -10,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::slice::SliceExt; -use std::old_io::{fs, USER_RWX}; -use std::process; +// no-prefer-dynamic + +#![feature(fs, process, env, path, rand)] + use std::env; -use std::old_path::BytesContainer; +use std::fs; +use std::process; use std::rand::random; +use std::str; fn main() { // If we're the child, make sure we were invoked correctly @@ -34,21 +35,20 @@ fn main() { fn test() { // If we're the parent, copy our own binary to a new directory. let my_path = env::current_exe().unwrap(); - let my_dir = my_path.dir_path(); + let my_dir = my_path.parent().unwrap(); let random_u32: u32 = random(); - let child_dir = Path::new(my_dir.join(format!("issue-15149-child-{}", - random_u32))); - fs::mkdir(&child_dir, USER_RWX).unwrap(); + let child_dir = my_dir.join(&format!("issue-15149-child-{}", random_u32)); + fs::create_dir(&child_dir).unwrap(); - let child_path = child_dir.join(format!("mytest{}", - env::consts::EXE_SUFFIX)); + let child_path = child_dir.join(&format!("mytest{}", + env::consts::EXE_SUFFIX)); fs::copy(&my_path, &child_path).unwrap(); // Append the new directory to our own PATH. let path = { let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap()).collect(); - paths.push(child_dir.clone()); + paths.push(child_dir.to_path_buf()); env::join_paths(paths.iter()).unwrap() }; @@ -58,9 +58,9 @@ fn test() { assert!(child_output.status.success(), format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}", - child_output.stdout.container_as_str().unwrap(), - child_output.stderr.container_as_str().unwrap())); + str::from_utf8(&child_output.stdout).unwrap(), + str::from_utf8(&child_output.stderr).unwrap())); - fs::rmdir_recursive(&child_dir).unwrap(); + fs::remove_dir_all(&child_dir).unwrap(); } diff --git a/src/test/run-pass/issue-16272.rs b/src/test/run-pass/issue-16272.rs index 3bab78ab0df..92d8dfa2cf9 100644 --- a/src/test/run-pass/issue-16272.rs +++ b/src/test/run-pass/issue-16272.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io::{process, Command}; +use std::process::Command; use std::env; fn main() { @@ -22,10 +22,8 @@ fn main() { } fn test() { - let status = Command::new(env::current_exe().unwrap()) + let status = Command::new(&env::current_exe().unwrap()) .arg("foo").arg("") - .stdout(process::InheritFd(1)) - .stderr(process::InheritFd(2)) .status().unwrap(); assert!(status.success()); } diff --git a/src/test/run-pass/issue-20091.rs b/src/test/run-pass/issue-20091.rs index 4d20e6360ad..ba107dd2cf9 100644 --- a/src/test/run-pass/issue-20091.rs +++ b/src/test/run-pass/issue-20091.rs @@ -8,14 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-windows currently windows requires UTF-8 for spawning processes - -use std::old_io::Command; -use std::env; - +#[cfg(unix)] fn main() { + use std::process::Command; + use std::env; + use std::os::unix::prelude::*; + use std::ffi::OsStr; + if env::args().len() == 1 { - assert!(Command::new(env::current_exe().unwrap()).arg(b"\xff") + assert!(Command::new(&env::current_exe().unwrap()) + .arg(::from_bytes(b"\xff")) .status().unwrap().success()) } } + +#[cfg(windows)] +fn main() {} -- cgit 1.4.1-3-g733a5 From e61a790495f49580fc0ee831bb07e00b4750b04a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 25 Feb 2015 13:58:58 +0530 Subject: Fix type inference error (fixup #22739) --- src/libstd/sys/windows/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 6e3b48a8f64..5bb2a134533 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -198,7 +198,7 @@ pub fn set_nonblocking(fd: sock_t, nb: bool) { if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) } != 0 { // The above function should not return an error unless we passed it // invalid parameters. Panic on errors. - Err(last_error()).unwrap(); + panic!("set_nonblocking called with invalid parameters: {}", last_error()); } } -- cgit 1.4.1-3-g733a5 From 2470fa155e8a0793d725891da2e6963c762fa674 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 25 Feb 2015 14:11:37 +0530 Subject: Assert is internal now (fixup #22739) --- src/libstd/sys/unix/pipe.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 1446600a77e..33863d31437 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -145,7 +145,7 @@ impl UnixStream { fd: self.fd(), guard: unsafe { self.inner.lock.lock().unwrap() }, }; - assert!(set_nonblocking(self.fd(), true).is_ok()); + set_nonblocking(self.fd(), true); ret } -- cgit 1.4.1-3-g733a5 From d54ed567e0714f6fac91b2f7f204a48a059b0f9f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 25 Feb 2015 14:15:24 +0530 Subject: path -> PathBuf for osx/dragonfly (fixup #22727) --- src/libstd/sys/unix/os.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 951c091f9f3..899280aa709 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -183,7 +183,7 @@ impl StdError for JoinPathsError { } #[cfg(target_os = "freebsd")] -pub fn current_exe() -> IoResult { +pub fn current_exe() -> io::Result { unsafe { use libc::funcs::bsd44::*; use libc::consts::os::extra::*; @@ -195,16 +195,16 @@ pub fn current_exe() -> IoResult { let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint, ptr::null_mut(), &mut sz, ptr::null_mut(), 0 as libc::size_t); - if err != 0 { return Err(IoError::last_error()); } - if sz == 0 { return Err(IoError::last_error()); } + if err != 0 { return Err(io::Error::last_os_error()); } + if sz == 0 { return Err(io::Error::last_os_error()); } let mut v: Vec = Vec::with_capacity(sz as uint); let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint, v.as_mut_ptr() as *mut libc::c_void, &mut sz, ptr::null_mut(), 0 as libc::size_t); - if err != 0 { return Err(IoError::last_error()); } - if sz == 0 { return Err(IoError::last_error()); } + if err != 0 { return Err(io::Error::last_os_error()); } + if sz == 0 { return Err(io::Error::last_os_error()); } v.set_len(sz as uint - 1); // chop off trailing NUL - Ok(Path::new(v)) + Ok(PathBuf::new::(&OsStringExt::from_vec(v))) } } @@ -227,7 +227,7 @@ pub fn current_exe() -> io::Result { unsafe { let v = rust_current_exe(); if v.is_null() { - Err(IoError::last_error()) + Err(io::Error::last_os_error()) } else { Ok(Path::new(CStr::from_ptr(v).to_bytes().to_vec())) } @@ -240,17 +240,17 @@ pub fn current_exe() -> io::Result { } #[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn current_exe() -> IoResult { +pub fn current_exe() -> io::Result { unsafe { use libc::funcs::extra::_NSGetExecutablePath; let mut sz: u32 = 0; _NSGetExecutablePath(ptr::null_mut(), &mut sz); - if sz == 0 { return Err(IoError::last_error()); } + if sz == 0 { return Err(io::Error::last_os_error()); } let mut v: Vec = Vec::with_capacity(sz as uint); let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz); - if err != 0 { return Err(IoError::last_error()); } + if err != 0 { return Err(io::Error::last_os_error()); } v.set_len(sz as uint - 1); // chop off trailing NUL - Ok(Path::new(v)) + Ok(PathBuf::new::(&OsStringExt::from_vec(v))) } } -- cgit 1.4.1-3-g733a5